Search Unity

DOTS - Multiplayer synchronization lags

Discussion in 'NetCode for ECS' started by Spy-Shifty, Oct 8, 2019.

  1. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Hi there,

    I testing around with the new dots multiplayer tech stack from github. So I took the Astroids sample from github and try to implement my own version with characters.

    My problem now is that the movement looks realy laggy. I think it comes from the quantization. When using a higher precision the lag is not that strong... It looks like that the character will try to move on a grid. So the prediction says: Ok my position is 1.5423 and the server says no you are at 1.5. Therefore the Character moves forward and on rollback it will snap back to the quantized position.

    Anyway I think I do something wrong or I miss something here. Because the Astroids sample runs without such lags... But my code does not look that different.

    My basic setup is similar to the astroid sample.

    So here is my setup:
    upload_2019-10-8_21-35-12.png
    The Hero shown in the scene is normaly not in the scene

    upload_2019-10-8_21-33-9.png

    upload_2019-10-8_21-33-59.png



    An here is my prediction movement system (client) and my movement system (server):

    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Collections;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5. using Unity.Mathematics;
    6. using Unity.Transforms;
    7.  
    8. [UpdateAfter(typeof(InputSystem))]
    9. [UpdateAfter(typeof(GhostReceiveSystemGroup))]
    10. [UpdateBefore(typeof(AfterSimulationInterpolationSystem))]
    11. [UpdateInGroup(typeof(ClientSimulationSystemGroup))]
    12. public class MovementPredictionSystem : JobComponentSystem
    13. {
    14.     private ClientSimulationSystemGroup _ClientSimulationSystemGroup;
    15.     private NetworkTimeSystem _NetworkTimeSystem;
    16.  
    17.     [BurstCompile]
    18.     [RequireComponentTag(typeof(HeroTagComponentData), typeof(PredictedEntityComponent))]
    19.     struct MovementJob : IJobForEach_BBCCC<HeroSnapshotData, HeroCommandData, Translation, Rotation, LocalToWorld> {
    20.  
    21.         public uint currentTick;
    22.         public float deltaTime;
    23.         public void Execute([ReadOnly] DynamicBuffer<HeroSnapshotData> snapshot, [ReadOnly] DynamicBuffer<HeroCommandData> input, ref Translation position, ref Rotation rotation, [ReadOnly] ref LocalToWorld localToWorld) {
    24.  
    25.             snapshot.GetDataAtTick(currentTick, out HeroSnapshotData snapshotData);
    26.  
    27.             // Iterate over last snapshot tick + 1 (we just applied the first one)
    28.             // to the current tick + 1 and apply prediction
    29.             for (uint tick = snapshotData.Tick + 1; tick != currentTick + 1; tick++) {
    30.                 input.GetDataAtTick(tick, out HeroCommandData inputData);
    31.  
    32.                 rotation.Value = math.mul(rotation.Value, quaternion.RotateY(math.radians(inputData.Look.x * deltaTime * 10))) ;
    33.                 position.Value += (localToWorld.Forward * inputData.Move.y + localToWorld.Right * inputData.Move.x) * deltaTime * 5;
    34.             }
    35.         }
    36.     }
    37.  
    38.     protected override void OnCreate() {
    39.         _ClientSimulationSystemGroup = World.GetOrCreateSystem<ClientSimulationSystemGroup>();
    40.         _NetworkTimeSystem = World.GetOrCreateSystem<NetworkTimeSystem>();
    41.     }
    42.  
    43.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    44.     {
    45.         var topGroup = World.GetExistingSystem<ClientSimulationSystemGroup>();
    46.  
    47.         var job = new MovementJob() {
    48.             deltaTime = topGroup.UpdateDeltaTime,
    49.             currentTick = _NetworkTimeSystem.predictTargetTick,
    50.         };
    51.  
    52.    
    53.         // Now that the job is set up, schedule it to be run.
    54.         return job.ScheduleSingle(this, inputDeps);
    55.     }
    56. }

    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Collections;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5. using Unity.Mathematics;
    6. using Unity.Transforms;
    7.  
    8. [UpdateAfter(typeof(HeroCommandReceiverSystem))]
    9. [UpdateInGroup(typeof(ServerSimulationSystemGroup))]
    10. public class MovementSystem : JobComponentSystem
    11. {
    12.     private ServerSimulationSystemGroup _ServerSimulationSystemGroup;
    13.  
    14.     [BurstCompile]
    15.     struct MovementJob : IJobForEach_BCCC<HeroCommandData, Translation, Rotation, LocalToWorld> {
    16.         public float deltaTime;
    17.         public uint currentTick;
    18.         public void Execute([ReadOnly] DynamicBuffer<HeroCommandData> input, ref Translation position, ref Rotation rotation, [ReadOnly] ref LocalToWorld localToWorld) {
    19.             input.GetDataAtTick(currentTick, out HeroCommandData inputData);
    20.  
    21.             rotation.Value = math.mul(rotation.Value, quaternion.RotateY(math.radians(inputData.Look.x * deltaTime * 10)));
    22.             position.Value += (localToWorld.Forward * inputData.Move.y + localToWorld.Right * inputData.Move.x) * deltaTime * 5;
    23.         }
    24.     }
    25.  
    26.     protected override void OnCreate() {
    27.         _ServerSimulationSystemGroup = World.GetOrCreateSystem<ServerSimulationSystemGroup>();
    28.     }
    29.  
    30.     protected override JobHandle OnUpdate(JobHandle inputDeps) {
    31.         var topGroup = World.GetExistingSystem<ServerSimulationSystemGroup>();
    32.         var job = new MovementJob() {
    33.             currentTick = _ServerSimulationSystemGroup.ServerTick,
    34.             deltaTime = topGroup.UpdateDeltaTime,
    35.         };
    36.  
    37.         return job.Schedule(this, inputDeps);
    38.     }
    39. }
    I hope that someone can help me.
    If you need more information feel free to ask me!

    EDIT:
    It looks like that the rollback and playback functionality isn't correct
     
    Last edited: Oct 9, 2019
  2. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,779
    Just wonder, how do you increase precision? By changing sampling frequence?
     
  3. daschatten

    daschatten

    Joined:
    Jul 16, 2015
    Posts:
    208
    You can adjust Quantization setting to get more precise numbers (e.g. for Translation from 10 to 1000), though more data has to be sent over network.
     
    Antypodish likes this.
  4. Flipps

    Flipps

    Joined:
    Jul 30, 2019
    Posts:
    51
    Excited to try the new DOTS netcode, too!

    Do you have a link to the new DOTS netcode on github?
     
  5. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Just Download the master
    https://github.com/Unity-Technologies/multiplayer?files=1

    Then go to samples and there you find the folder netcode. Inside there, you'll find a folder documentation with quick start instructions and a brief overview of the netcode.
    By the way, this is not the unite demo but it's similar to it...
    Try to start with the astroids sample. It's not too hard to get in. I recommend to watch the unite session about the netcode on YouTube.

    https://github.com/Unity-Technologi...t/Assets/NetCode/Documentation~/quickstart.md

    https://github.com/Unity-Technologi...ject/Assets/NetCode/Documentation~/netcode.md

     
    Flipps likes this.
  6. Flipps

    Flipps

    Joined:
    Jul 30, 2019
    Posts:
    51
    Thank you very much for the nice explanation! Going to try it out right now :)
     
    Spy-Shifty likes this.
  7. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Ok, I made a video of the problem.

    I also changed the send receive delay to 250ms
    upload_2019-10-9_19-23-26.png

    Now it looks like that the problem is the Rollback funktion...
     
  8. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    And this is how it looks like with an extreme delay of 1 second:

    I start to move, then I release the button. Now it snaps back to the starting position and after a second, it moves to the destination position...

    So now I would say that the tick rate isn't calculated correctly.
    Very weird

     
  9. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    967
    Hey!
    I had the same issues.
    First thing is to use a quantization of at least 1000.
    Then I did a tick by tick analysis from server and client and came to the conclusion that the for loop is wrong and it has to start at the snapshot.tick and not +1

    I use this loop: for (uint tick = snapshotData.Tick; tick != currentTick + 1; ++tick)
    The analysis afterwards had no wrong predictions anymore. I use a hybrid model so that part could be only on my side.

    Even with accurate predictions I had jittery movement. Not really visible from outside but with a 3rd person camera it got apparent that the movement is not fluid at all.

    I could find the root cause of this was the interpolation system. It has a bug that I couldn't find even with lots of debugging. I just threw it out. Sure, would be nice but it works fine without any now.

    edit: The asteroid sample doesn't run fine when you increase the velocity. For testing purposes I applied velocity instantly instead of gradually and didn't spawn any asteroids to actually test. Movement will skip and jitter at faster speeds.
     
  10. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Many thanks! I'll try it out and write my feedback to it later on :)
     
  11. pal_trefall

    pal_trefall

    Joined:
    Feb 5, 2019
    Posts:
    78
    This is still the 3 month old version though, right? Been holding my breath for the 2019.3 updated one.
     
  12. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Yep, it is.
     
    pal_trefall likes this.
  13. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    967
    pal_trefall likes this.
  14. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    We are planning for a new entities release next week.
     
  15. Justin_Larrabee

    Justin_Larrabee

    Joined:
    Apr 24, 2018
    Posts:
    106
    Will the new multiplayer sample from Unite drop around the same time by any chance?
     
  16. pal_trefall

    pal_trefall

    Joined:
    Feb 5, 2019
    Posts:
    78