I’ve run into this issue when implementing a visibility system for some pickups that spawn all over the map.
I have logic running on every tick that checks a visibility range and then calls NetworkObject.NetworkShow for the associated client. The pickup also has an OnTriggerEnter callback that calls despawn on the network object. There is an edge case here where the despawn gets triggered after the NetworkShow call, but before the next tick where the “ObjectsToShowToClient” list actually gets processed.
so the flow looks something like this
Tick A)
- NetworkBehaviourUpdater: HandleNetworkObjectShow (nothing to show)
- Pickup: VisibilityCheck (calls NetworkShow)
In-Between Ticks
- Pickup: OnCollisionEnter (calls Despawn which immediately destroys the gameobject)
Tick B)
- NetworkBehaviourUpdater: HandleNetworkObjectShow (object in the
ObjectsToShowToClient list has been destroyed, causing the foreach loop to throw a null reference exception
Since the ObjectsToShowToClient never clears (on account of the exception) this error will repeat every frame forever and ever preventing any new objects from being shown to clients
Workaround:
My workaround for now is to basically mark the object for destruction but not actually call the despawn until the next network tick. That way any pending “shows” can be processed before the object is despawned. This workaround works but it seems like a bug to me that this would be necessary. Furthermore it doesn’t seem ideal that a network show would wait an entire tick to actually be sent out to clients but I suppose this is consistent with how updates to network variables are handled so it makes sense