Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

NetworkVariableBase performing multiple WriteDelta calls?

Discussion in 'Netcode for GameObjects' started by Salmonman, Feb 9, 2023.

  1. Salmonman

    Salmonman

    Joined:
    Jul 14, 2016
    Posts:
    23
    I'm using NetworkVariableBase to set up an ItemContainer class for a networked inventory system, which means I'm using the WriteField, ReadField, WriteDelta, and ReadDelta methods. I return to test the system after a few weeks not working on it to find it completely broken, and hours of tracing code has revealed the problem to be that WriteDelta is being called multiple times (once for the server, and then once per connected client), and the queues I'm using to hold update information were being emptied by the first call and then obviously remain empty for subsequent calls when they shouldn't be.

    Long story short: I know my code worked a few weeks ago, and I haven't changed those methods at all since then, so was there some update to NGO that's causing this new behaviour? Is it a bug, or is that just how NetworkVariables work? I would expect that it would only have to write the state of the variable to the message buffer once, because that should be the correct data for all clients observing the variable, it shouldn't need to build identical copies of the buffer for each client.
     
  2. RikuTheFuffs-U

    RikuTheFuffs-U

    Unity Technologies

    Joined:
    Feb 20, 2020
    Posts:
    440
    Did you update NGO / Unity? From which version to which other one?
    If not, the issue is probably in what changed in your code.
     
  3. Salmonman

    Salmonman

    Joined:
    Jul 14, 2016
    Posts:
    23
    I believe my code was working correctly in version 2021.3.16, and I'm currently operating on 2021.3.18f1
    NGO is on 1.2.0 and looks like it has been since December 9th

    So yeah, I can see where you're coming from, since it doesn't seem like anything should have changed since then except my own code, but I'm sure it didn't. I know for a fact that I was testing the system with a connected client before, and the method was only being called once because the queue wasn't being emptied prematurely like it is now.

    The real question remains the same, should WriteDelta be getting called once for the server and again for each observing client? I don't think it was before, and I don't think it should be now, but it is.
     
  4. NoelStephens_Unity

    NoelStephens_Unity

    Unity Technologies

    Joined:
    Feb 12, 2022
    Posts:
    252
    @Salmonman
    I don't think this functionality has changed, but I can shed some light as to what might be happening. The best way to do this is to walk through how the code arrives to the NetworkVariableBase.WriteDelta method.
    Every network tick NetworkBehaviourUpdater.NetworkBehaviourUpdate is invoked.
    Within NetworkBehaviourUpdate, all NetworkObjects that have NetworkBehaviour components with dirty NetworkVariables will have their NetworkBehaviour.VariableUpdate method invoked (once for server and once for each observing client).

    For the server and each observing client:
    NetworkBehavior.NetworkVariableUpdate is invoked directly from Variable update.
    Within this method a NetworkVariable delta is serialized in one of two places:
    If the server is sending it to itself (i.e. host), then it serializes the method directly without sending a message.
    It sends a NetworkVariableDeltaMessage to each observing client where serialization occurs as well.

    Within NetworkVariableDeltaMessage.Serialize there are two places that call NetworkVariableBase.WriteDelta and that depends upon whether your NetworkManager is configured to ensure NetworkVariable Length Safety or not.

    So the summary is:
    • Each network tick NetworkBehaviourUpdater.NetworkBehaviourUpdate is invoked
    • Each NetworkObject that has NetworkBehaviours with dirty NetworkVariables will be iterated over
    • For each observer (depending upon permissions etc) both the server and client(s) will be updated/synchronized with the deltas for each NetworkVariable. (this is basically a loop)
      • During the serialization for the target (server or client) NetworkVariableBase.WriteDelta is invoked
    That occurs in the same frame for each new network tick, so the behavior where it is invoked for the server (i.e. host) and any connected client has been the same behavior for awhile now.

    If you wanted to share your NetworkVariableBase derived class I could look over it and see if I can find anything in there that could be the cause. Not having looked at your code, I think resetting your queue when NetworkVariableBase.ResetDirty is invoked as opposed to when WriteDelta is invoked will assure that your queue persists while it writes all of the deltas but is reset when NGO has finished sending delta updates so your NetworkVariableBase derived class can repopulate the queue later in that same frame when normal MonoBehaviour.Update methods are invoked.
     
    Last edited: Feb 13, 2023