Table of Contents

Class ObserverBudgetCondition

Namespace
FishMMO.Shared
Assembly
FishMMO.Shared.dll

Caps how many CHARACTERS one client observes at a time, keeping the most relevant.

[CreateAssetMenu(menuName = "FishMMO/Observers/Observer Budget Condition", fileName = "ObserverBudgetCondition")]
public class ObserverBudgetCondition : ObserverCondition, IOrderable
Inheritance
Object
ScriptableObject
ObserverCondition
ObserverBudgetCondition
Implements
IOrderable
Inherited Members
ObserverCondition.NetworkObject
ObserverCondition.Order
ObserverCondition.IsConstant
ObserverCondition.GetIsEnabled()
ObserverCondition.Initialize(NetworkObject)
ScriptableObject.SetDirty()
ScriptableObject.CreateInstance<T>()
Object.GetEntityId()
Object.GetInstanceID()
Object.GetHashCode()
Object.InstantiateAsync<T>(T)
Object.InstantiateAsync<T>(T, Transform)
Object.InstantiateAsync<T>(T, Vector3, Quaternion)
Object.InstantiateAsync<T>(T, Transform, Vector3, Quaternion)
Object.Instantiate(Object, Vector3, Quaternion)
Object.Instantiate(Object, Vector3, Quaternion, Transform)
Object.Instantiate(Object)
Object.Instantiate(Object, Scene)
Object.Instantiate<T>(T, InstantiateParameters)
Object.Instantiate<T>(T, Vector3, Quaternion, InstantiateParameters)
Object.Instantiate(Object, Transform)
Object.Instantiate<T>(T)
Object.Instantiate<T>(T, Vector3, Quaternion)
Object.Instantiate<T>(T, Vector3, Quaternion, Transform)
Object.Instantiate<T>(T, Transform)
Object.Destroy(Object)
Object.DestroyImmediate(Object)
Object.DontDestroyOnLoad(Object)
Object.DestroyObject(Object)
Object.FindObjectsOfType<T>()
Object.FindObjectsByType<T>(FindObjectsSortMode)
Object.FindObjectsByType<T>(FindObjectsInactive, FindObjectsSortMode)
Object.FindObjectOfType<T>()
Object.FindFirstObjectByType<T>()
Object.FindAnyObjectByType<T>()
Object.FindFirstObjectByType<T>(FindObjectsInactive)
Object.FindAnyObjectByType<T>(FindObjectsInactive)
Object.FindObjectsByType<T>()
Object.FindObjectsByType<T>(FindObjectsInactive)
Object.ToString()
Object.name
Object.hideFlags

Remarks

Distance alone does not bound a client's cost: a hundred players can stand inside any radius you pick. This is the bound. ObserverStreamingRegistry already ranks every character a viewer could see by relevance — combat, party, guild, distance — and this condition simply admits the top ObserverStreamingPolicy.VisibilityBudget of them.

It gates existence, not fidelity. A character outside the budget is not merely slowed down; it is despawned on that client, taking its audio, nameplate, buffs and every broadcast with it. That is why it must be the LAST condition — everything cheaper should have rejected first — and why it is rank-hysteretic: two characters of near-identical score either side of the boundary would otherwise spawn and despawn each other every pass, which costs far more than any rate change and reads as flicker.

It only budgets registered characters. Anything else — interactables, world items, scene objects, a character whose entry has not been created yet — is admitted untouched, so this is safe to install as a default condition on every object. Their absence would be far more confusing than a missing distant stranger, and they are cheap.

Party members within the ability ceiling and the viewer's current target are pinned by the registry and can never be evicted, however dense the crowd gets.

Methods

ConditionMet(NetworkConnection, bool, out bool)

Whether connection may observe this object under its visibility budget.

public override bool ConditionMet(NetworkConnection connection, bool currentlyAdded, out bool notProcessed)

Parameters

connection NetworkConnection

The connection being tested.

currentlyAdded bool

True when the connection already observes this object.

notProcessed bool

True when this condition could not decide, which tells FishNet to keep the previous result. Used while a viewer has no ranking yet: the alternative — answering "false" — would hide the world from every client that connects between two scheduler passes.

Returns

bool

True when the object is inside the budget.

GetConditionType()

Timed: the ranking changes as characters move and fight, so this has to be re-evaluated on the observer sweep rather than only when something structural happens.

public override ObserverConditionType GetConditionType()

Returns

ObserverConditionType