Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

Networking Prevent SyncVar from replicating to local player

Discussion in '5.1 Beta' started by ObliviousHarmony, May 14, 2015.

  1. ObliviousHarmony

    ObliviousHarmony

    Joined:
    Jul 3, 2014
    Posts:
    79
    Hello,

    I'm currently working on switching over to UNet from my current networking middleware and I've run into a small dilema. In the middleware I was using, it was possible to declare whether or not a specific property was synchronized to the local player, but that doesn't seem to be the case in UNet. To clarify, this is in a circumstance where the server has authority, but the client sends commands and the like to the server. This also extends to NetworkTransform and NetworkAnimator I would assume, in that the controlling client will have its current state overridden by what the server sends down.

    To expand further, the specific use case for this is client-side prediction and lag compensation. To do it properly, I need to be able to prevent the transforms from being synchronized to the local player (but synchronized to all other clients). With that, I'd also need to prevent the Animator from syncing, as it would also make the entire setup look very strange.

    I was wondering if maybe I was missing something, or if there's just no way to do this presently. If there isn't, is it perhaps something that will be making its way into UNet? Perhaps a property in the network classes, and an additional parameter to the SyncVars attribute? :D
     
  2. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    The "local Player Authority" checkbox on the NetworkIdentity is for this. If you check it for your player prefab, then the NetworkTranform sends movement data from the local client to the server, then out to other clients.

    The NetworkAnimator is supposed to work like that too, but there is a bug in beta6 that is preventing it.

    SyncVar updates are sent to all clients, but you can ignore them on a client if you make a hook function..

    [SyncVar(hook=OnVar)]
    int var;

    // will be called on clients when var changes on server
    void OnVar(int value)
    {
    if (localPlayer)
    return;

    var = value;
    }
     
  3. ObliviousHarmony

    ObliviousHarmony

    Joined:
    Jul 3, 2014
    Posts:
    79
    Hey Sean,

    Thanks for the reply!

    With regards to local player authority, as I mentioned in the initial post, the use case is for client-side prediction. The issue with giving the local client authority is that their client has control over ALL SyncVars, which is undesirable. As for the hooking, I'd actually though of doing that but I was hoping there would be a way to avoid sending the sync to the client entirely, as it's a waste of bandwidth if it doesn't need to get sent.

    As for NetworkAnimator and NetworkTransform, I also recognize that it's possible to roll a solution using the serialization methods, but I was just curious if this might be something that was planned for UNet. It feels like a relatively simple change, versus rewriting all of the functionality for both of those classes.

    Edit: Another thought just came to mind actually. I need to test it tomorrow when I'm at my workstation, but it might be possible to override the serialize methods for those two classes and just return true for the local player. Assuming they use them (I hope they do!)

    Edit 2: Again though, it would be nice to not send the data at all.
     
    Last edited: May 15, 2015
  4. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    "the local client authority is that their client has control over ALL SyncVars, which is undesirable"?

    That is not what the LocalPlayerAuthority fla
     
  5. ObliviousHarmony

    ObliviousHarmony

    Joined:
    Jul 3, 2014
    Posts:
    79
    Hey Sean,

    Upon deeper examination of the "NetworkBehaviour" class, it seems that you are indeed correct. I misunderstood the documentation on authority, so that's exciting. I can then also use hooks to reject changes on the controller that I don't want, and override the serialization methods for NetworkTransform and NetworkAnimator to do the same. It still wastes bandwidth, but it is at least possible to do what I'm attempting!

    Thanks for the help!
     
  6. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    sorry my reply got truncated..

    You dont need to override OnDeserialize on NetworkTransform, it already checks hasAuthority and does the right thing.
     
  7. ObliviousHarmony

    ObliviousHarmony

    Joined:
    Jul 3, 2014
    Posts:
    79
    Once again, the use-case for this client-side prediction and lag compensation :p To further clarify, I'm working on implement a command queue into UNet. How this works is actually rather simple. The client records the frame that a command takes place, adds it to a queue, and sends it to the server. It also then processes the same command locally. (To clarify on what a command is here, it's an struct that contains inputs and outputs.

    How this works is actually rather simple. There is a command struct which contains inputs (mouse/keyboard buttons), and outputs (position/rotation/etc). Every so often we will aggregate this information (every key press since the last time we did it), and add it to a local queue with the frame number. At the same time, we will send this command to the server. On the client, we will run it through a command execution method, immediately performing the action and recording the results in the command locally. The server will receive the command, run the exact same action method, and then return its results to the client.

    Once this is received from the server, the frame number is used to find the local command and update it with the position/rotation from the server. From there, we call the aforementioned command execution method on every command in the queue starting at this last "correction" from the server, used as the initial state. The end result is that the server is authoritative over the player's movement, but the player's local client is able to immediately move, without worrying about what the server.

    The great thing about this is that as long as the server's world-state matches the client, for the most part, no corrections will actually make a change in the player's position on the client. In most cases as well, corrections should be small and there won't be any jittering because you're not directly setting the position based on the server's view of where you were ~100ms ago, but rather using that to extrapolate where you will be once the rest of the commands get processed on the server.