Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Question Jitter while syncing players movements

Discussion in 'Multiplayer' started by imM4TT, May 25, 2024.

  1. imM4TT

    imM4TT

    Joined:
    Dec 6, 2017
    Posts:
    8
    Context:

    I'm using a Client-Server architecture with DarkRift Networking. I recently studied a bit about the Netcode. (BTW if you are interested about the Netcode, these are pretty nice resources: 1, 2, 3)

    At this stage I have the following network implementation (simplified version):

    1. Client predict and render his own simulation then send it to the server (FixedUpdate)

    2. Server save every Client simulations when received

    3. Server periodically send last simulation to every Client

    4. Non-local Client data is received/saved by every Client and will be updated on the next Client simulation (FixedUpdate)
    --

    I'm currently trying to figure out an unexpected behavior of player movements being synchronized.

    Players positions and rotations are correctly synced however it looks like the follow camera script induce jitter for non-local players. When I disable the follow camera script from the scene view and go back to the game, jitter suddently disapears.

    OK, I can understand that jitter must exist especially that currently I'm not using Lerp to update non-locals players transforms. BUT why when the follow camera script is disabled, the jitter is not here anymore ?

    The script for my camera work in LateUpdate, and it simply smoothly follow the local player. Player movements in my game are constantly forward (think about a car that's always going forward).

    After some tests: Building and starting the app(2x instances), when camera is not following the local player then both players movements are smooth.

    Any idea ?

    Edit: There is a short clip of the problem
     
    Last edited: May 25, 2024
  2. Kakr-98

    Kakr-98

    Joined:
    Apr 29, 2020
    Posts:
    36

    Probably an ordering issue somewhere. That's what the majority of jitter issues are caused by.
     
  3. Kakr-98

    Kakr-98

    Joined:
    Apr 29, 2020
    Posts:
    36
    On a second look, if you are interpolating one of the cars and not the other, surely you will have jitter looking at A car when following B car.

    One of them is being moved at the simulation rate, and the other moved at the framerate (due to interpolation).

    You are not seeing the jitter when the follow script is disabled is because it's harder to do that compared to when the actual camera transform is being moved in a different rate than one of the objects in the view.
     
    Last edited: May 26, 2024
    CodeSmile likes this.
  4. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,922
    Looks like interpolating only between two ticks. However you can assume, and this is clearly the case for this test, that any movement continues at the same rate.

    So it's either trying to interpolate and then gets the new position (out of order) or it's not interpolating the right distance (predicts and interpolates at 60 Hz but logic runs at 50 Hz). Both already pointed out by Kakr.

    You should not force the authoritative position on the object (except when the positions deviate more than a given threshold) and then interpolate, but rather adjust the next interpolation phase accordingly.

    So if the authoritative position were to set the car back a little, instead of applying this new position and interpolating from there you would extrapolate the authoritative position to where it will be next, then interpolate from the current position to the new extrapolated position. This means the car's interpolated speed will be a little slower which is less noticeable for the player's eyes.
     
  5. imM4TT

    imM4TT

    Joined:
    Dec 6, 2017
    Posts:
    8
    I'm nut sure to fully understand the given explanations, also my english don't help much haha, you may be right though ...
    I would rather say that both of them are being moved at the simulation rate with their respectives last known positions (without interpolation).
    Edit: thinking again about your explanations, you are saying that the jitter is more pronounced due to the fact that the transform of the camera is being updated on a different rate (more often) than the non-local players ? If so, how can I deal with it ?


    There is no interpolation at all. I mean I don't use Lerp or this kind of method to "smoothly" move players but instead their positions are updated by RigidBody.Move().
    Also I use a SortedSet to store local/non-locals movements, it can't be an issue related to an incorrect order of positions.
    Code (CSharp):
    1. private void FixedUpdate()
    2. {
    3.    if (isLocalPlayer)
    4.    {
    5.       Quaternion localRotation = ... ;
    6.       Vector3 localPosition = ;
    7.       rb.MoveRotation(localRotation);
    8.       rb.MovePosition(localPosition);
    9.    }
    10.    else
    11.    {
    12.       Quaternion netRotation = ... ; // Last known transforms of this player
    13.       Vector3 netPosition = ... ; // ...
    14.       rb.MoveRotation(netRotation);
    15.       rb.MovePosition(netPosition);
    16.    }  
    17. }
    Again, I'm not sure to understand.
    If you are talking about non-local players, how could I force a new position and then apply interpolation since the new position would actually be the last known position ?

    --
    I may miss something, I mean I still don't understand. Could you please try to re explain (also I provided more informations that can be usefull).
    I'm grateful for the help provided.
     
    Last edited: May 26, 2024
  6. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,922
    Simulating non-kinematic (non-deterministic) physics over the network is no mean feat and few games do it.

    If the physic simulation happens on the server, the whole physics simulation is latent and at odds with what the local player is doing. If physics simulation is done on every client, their state of the world is at odds with everyone else's.

    Normally a network framework will do the synchronization for you.
    What I propose is that you get the new position from the server outside the automated systems, and apply it yourself.

    What does it sort by?
     
  7. imM4TT

    imM4TT

    Joined:
    Dec 6, 2017
    Posts:
    8
    It's not like I'm using complicated methods to simulate locally, instead Rigidbody.Move() should be 99.99% the same than a direct transform.Translate() ?

    If you meant to have a specific function that update non-local players movements at the moment their positions are received by the Client (so outside FixedUpdate), that's how I was doing this before but it shouldn't be more consistent ? It tends to be the opposite ?

    It's sorted by the index attached to the movement corresponding to the local player nth simulation.
    So when a Client receive a simulation from the server, he knows the corresponding index of this simulation.
     
    Last edited: May 26, 2024
  8. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,922
    Yes but I assume you are using physics to do an actual physics simulated game. If not, it's best to use direct transform changes because then you don't need the overhead of having a rigidbody.

    Kind of what we're trying to tell you. There must be some issue with your approach, and it's likely an execution order thing. I doubt that a locally sorted set will help with this, in fact it could actually become a problem when every client has its own sort order.

    There is no guarantee that you'll be receiving these simulation steps in order. ;)
    What should be 1 2 3 4 5 6 7 8 9 could be received as 1 2 3 4 6 5 7 8 9.
    You only get to sort the 5 back in place after you ran the 6th step.

    This isn't necessarily the cause of the issue you are having but it can generally become an issue when testing over the internet and depending on whether DarkRift by itself discards any out of order (unreliable) packets.
     
  9. imM4TT

    imM4TT

    Joined:
    Dec 6, 2017
    Posts:
    8
    Understood.


    I don't think there is any issue here. My explanations was not necessarily good but since the Client know the index rattached to the received simulation then he can store them orderly.
    Let's say Client receive 1, 3, 2, 4. He gonna store them as 1, 2, 3, 4 and also simulate the last known simulation based on the index.
    When he receives 1, he simulates 1. When he receives 3, he simulates 3. When he receives 2 he currently skips it.
    Edit: Actually I don't know if my issue can be related to this or not.

    Thanks again for your time and your help.