Class ObserverBudgetCondition
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
-
ObjectScriptableObjectObserverConditionObserverBudgetCondition
- Implements
-
IOrderable
- Inherited Members
-
ObserverCondition.NetworkObjectObserverCondition.OrderObserverCondition.IsConstantObserverCondition.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.nameObject.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.
Every classification gets its own budget. Players, Monsters, Interactables, World Items, Waypoints and Titans are ranked and capped separately, so a crowd of one kind can never squeeze out another — which it used to: forty players in a town square evicted the banker they were queueing for, because one shared budget ranked a stationary service NPC below every living thing near it. The budget for each kind is authored on its ClassifiedDistanceCondition asset, where 0 means unlimited.
Unclassified objects are admitted untouched. Scene objects and anything whose distance condition is a plain FishNet one have no budget to be measured against, so this is safe to install as a default condition on every object.
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
connectionNetworkConnectionThe connection being tested.
currentlyAddedboolTrue when the connection already observes this object.
notProcessedboolTrue 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