Search Unity

[Netcode] prediction jitter

Discussion in 'NetCode for ECS' started by wechat_os_Qy0zfuyEv3KJOsvT_cd-jV0I0, Oct 10, 2020.

  1. wechat_os_Qy0zfuyEv3KJOsvT_cd-jV0I0

    wechat_os_Qy0zfuyEv3KJOsvT_cd-jV0I0

    Joined:
    Apr 29, 2020
    Posts:
    7
    Hello,
    When I run the getStarted Netcube demo, there seems some jitter movements.
    Like below, when the other players move, there is no jitter in my client.
    https://drive.google.com/file/d/1xpNz72p-7QdAGGD-dWZJr_wVTkSpjsM6/view?usp=sharing
    But if I move my cube, the cube jitters few seconds after it stops simulation. How does this come?
    https://drive.google.com/file/d/1cruv5w4bMIsAhV6uqTYBdxpjMdK5saFX/view?usp=sharing
    Commenting out the prediction code in GhostPredictionSystemGroup solve the jitter. However, it seems as no prediction but only interpolation.
     
    Last edited: Oct 10, 2020
  2. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I had this as well. I don't know what's happening but I think maybe it could be the result of floating point precision issues that add up over several frames of simulation? It's probably the kind of thing that we'll need to wait for a Netcode package update in order to solve it.
     
  3. wechat_os_Qy0zfuyEv3KJOsvT_cd-jV0I0

    wechat_os_Qy0zfuyEv3KJOsvT_cd-jV0I0

    Joined:
    Apr 29, 2020
    Posts:
    7
    Hi,
    Thanks for your reply, that is where the problem exactly is. The implementation of CopyToSnapshot and CopyToSnapshot in Assets\NetCodeGenerated\Unity.Transforms.Generated\Unity.Transforms.TranslationSerializer.cs makes the precision to be 0.01f. Changing them or changing the precision in your prediction code solves the problem.
    Now I am finding where to fix them more normally. The GhostField[Quantization=...] may solve the problem, but there seems no effect and maybe there is a template to fix the quantization...
     
    adammpolak and PhilSA like this.
  4. wechat_os_Qy0zfuyEv3KJOsvT_cd-jV0I0

    wechat_os_Qy0zfuyEv3KJOsvT_cd-jV0I0

    Joined:
    Apr 29, 2020
    Posts:
    7
    The Quantization is not easy to change TranslationSerializer with Netcode generated automatically.
    GhostAuthoringComponentEditor sets 100 to quantization of translation. It is possible to modify it outside like below.
    upload_2020-10-13_16-6-34.png
    However, I can not find how it makes effect before code generation. Also failed to set generation manually by using GhostCompilerService or GhostCompilerServiceWindow methods...
    Is there anyway to modify the quantization offically? GhostField[Quantization=...] no effect..
     
  5. kanesteven

    kanesteven

    Joined:
    Aug 30, 2018
    Posts:
    45
    @timjohansson Can you confirm that this assessment is indeed correct? I am not really seeing this jitter in my own personal project and thus am skeptical of the diagnosis although I am also quite surprised that the quantization used for translation is relatively low.
     
  6. mpcomplete

    mpcomplete

    Joined:
    Feb 20, 2019
    Posts:
    4
    The Unity docs suggest an alternate way to override the ghost defaults here[1]. From my understanding, these take effect before your game's runtime. Here's a sample implementation:

    Code (CSharp):
    1. public class GhostOverrides : IGhostDefaultOverridesModifier {
    2.   public void Modify(Dictionary<string, GhostAuthoringComponentEditor.GhostComponent> overrides) {
    3.     overrides["Unity.Transforms.NonUniformScale"] = new GhostAuthoringComponentEditor.GhostComponent {
    4.       name = "Unity.Transforms.NonUniformScale",
    5.       attribute = new GhostComponentAttribute { PrefabType = GhostPrefabType.All, OwnerPredictedSendType = GhostSendType.All, SendDataForChildEntity = false },
    6.       fields = new GhostComponentField[] {
    7.         new GhostComponentField {
    8.           name = "Value",
    9.           attribute = new GhostFieldAttribute{Quantization = 100, Interpolate = true}
    10.         }
    11.       },
    12.       entityIndex = 0
    13.     };
    14.   }
    15.  
    16.   public void ModifyAlwaysIncludedAssembly(HashSet<string> alwaysIncludedAssemblies) {
    17.     alwaysIncludedAssemblies.Add("Unity.Transforms.NonUniformScale");
    18.   }
    19.  
    20.   public void ModifyTypeRegistry(TypeRegistry typeRegistry, string netCodeGenAssemblyPath) {
    21.   }
    22. }
    [1] https://docs.unity3d.com/Packages/com.unity.netcode@0.4/manual/ghost-snapshots.html - search for IGhostDefaultOverridesModifier
     
    kanesteven likes this.
  7. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    The quantization factor needs to be tweaked based on your game (how close to the objects you are, what 1 unit maps to in m/cm/ft/etc), but a factor of 1000000 looks way bigger than I would expect, and you might actually be better off not quantizing it at all at that point (Quantization=-1).
    You need to use the IGhostDefaultOverridesModifier and it needs to be in an assembly named something ending with ".NetCodeGen" to be picked up. The flow is not easy to work with and we are currently looking at overhauling it to make it easier to tweak these override values.
    We are also working on improving the behavior on small miss-predictions like this so it is smoother.
     
    MehO and optimise like this.
  8. wechat_os_Qy0zfuyEv3KJOsvT_cd-jV0I0

    wechat_os_Qy0zfuyEv3KJOsvT_cd-jV0I0

    Joined:
    Apr 29, 2020
    Posts:
    7
    Thanks for your help! The problem is solved now. It needs a new asmdf file with .NetcodeGen. And a script in the same folder to override the GhostDefaultOverridesModifier.
    upload_2020-10-27_10-30-26.png
    But the origin ambition to do this is to fix the phenomenon below. Quantization can fix the lag after movement, while not fixing the lag of other players moving in your client. Even when establishing a work like NetCube, when two players move forward at the same spped, the lag/snap exists. the move and camera folllow logic have been checked carefully..
    https://drive.google.com/file/d/1__K1P_8BslqpjggELMTn_bpg7TA5S0xZ/view?usp=sharing
     
  9. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    I am not sure what to look for in the video posted. The robots are tilting when moving which makes it hard to see if they are moving unevenly or just tilting while moving.

    Other players moving will always have a delay if they are interpolated - is that what you mean by the lag of other players?
    All interpolated ghosts are displayed at the last received server state minus interpolation delay, predicted ghosts are displayed at the tick the server will have when the commands for the current frame arrive on the server. Put another way, interpolated ghosts show an old server tick, predicted ghosts show a future server tick that has not happened yet.
     
  10. wechat_os_Qy0zfuyEv3KJOsvT_cd-jV0I0

    wechat_os_Qy0zfuyEv3KJOsvT_cd-jV0I0

    Joined:
    Apr 29, 2020
    Posts:
    7
    Thx very much again for your reply! Sorry for describing it as a lag problem, actually,it is maybe a problem about moving unevenly. The NetCube is experimented on now. As below, the X axis is UnityEngine.Time.time, and the Y axis is the position of the cube. And the purple line is the position from server,while the red line is the one from client.
    When the ghost cube is predicted,
    NetworkTest 绘图(time-position-predicted).png
    When the ghost cube is interpolated,
    NetCube 绘图(time-position-interpolated).png
    The position is accumulated by deltaTime, so it should move in uniform speed.
    But it moves unevenly, which may cause the problem that the shaking phenomenon is more obvious when moving forward together with other players.
     
    Last edited: Oct 27, 2020
    PhilSA and Lukas_Kastern like this.
  11. Lukas_Kastern

    Lukas_Kastern

    Joined:
    Aug 31, 2018
    Posts:
    97
    We've been experiencing the same jitter. It's more noticeable when walking/running next to an interpolated character for us.
     
  12. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    The time we used for interpolated ghosts is calculated as an offset from the time we use for prediction - based on RTT and deviance. It looks like we need to tweak those calculations to be more smooth. Can you please file a bug for this issue?
     
  13. anihilnine

    anihilnine

    Joined:
    Jan 29, 2016
    Posts:
    27
    cdm456852 likes this.
  14. kanesteven

    kanesteven

    Joined:
    Aug 30, 2018
    Posts:
    45
    @timjohansson did this bug get filed / fixed in 0.5.0? I am thinking not as I am running 0.5.0 and have increased the quantization of both Translation and Rotation through the custom .NetCodeGen assembly definition but I still see the same jitter.
     
    Lukas_Kastern likes this.
  15. wechat_os_Qy0zfuyEv3KJOsvT_cd-jV0I0

    wechat_os_Qy0zfuyEv3KJOsvT_cd-jV0I0

    Joined:
    Apr 29, 2020
    Posts:
    7
    @timjohansson@anihilnine @kanesteven @Lukas_Kastern
    Hi,I read the NetworkTimeSystem to research into the reasons and find some clues.
    The PredictTargetTick advances by the tickrate of client, which is determinated by the commandAge or the repredict "curpredict".
    The InterpolateTargetTick advances by the subInterpolateTargetTick, which is determinated by the estimateedRTT and the DeviationRTT. The advance step is determinated by the last subInterpolateTargetTick, subPredictTargetTick and the fraction part of currentInterpolationFrames.
    After all, the advance steps of predict and interpolate are different, whose D-value is the interpolationDelay that may introduce uneven movement.
    ----
    By the way, there are some unnecessary calculation of subInterpolateTargetTick. subidiff is the fraction part of currentInterpolationFrames, 0<subidiff<1. Then when subidiff -= subInterpolateTargetTick + subPredictTargetTick>0, the subidiff is also between 0 and 1. So
    idiff = (uint)subidiff;
    subidiff -= idiff;
    interpolateTargetTick -= idiff;
    do noting...
     
    bb8_1, Enzi and Lukas_Kastern like this.
  16. anihilnine

    anihilnine

    Joined:
    Jan 29, 2016
    Posts:
    27
    Today I found the my client's idea of ServerTick was getting way ahead of the Server's actual ServerTick. This was solved by actually having an ICommandData buffer somewhere eg
    commandBuffer.AddBuffer<CubeInput>(player);


    I didn't have a commandBuffer yet because my client can't issue commands yet. However having it somehow keeps the client and server ticks in sync. So make sure you have an ICommandData buffer somewhere.
     
  17. Lukas_Kastern

    Lukas_Kastern

    Joined:
    Aug 31, 2018
    Posts:
    97
    I just took a look at the NetworkTimeSystem, and I don't quite understand it.
    I thought the time calculation of the fps sample was complex but this just blows my mind.

    Is there something I can look up to understand it better?
     
    bb8_1 likes this.
  18. bb8_1

    bb8_1

    Joined:
    Jan 20, 2019
    Posts:
    100
    Last edited: Nov 21, 2020
    Lukas_Kastern likes this.
  19. Lukas_Kastern

    Lukas_Kastern

    Joined:
    Aug 31, 2018
    Posts:
    97
    bb8_1 likes this.
  20. Lukas_Kastern

    Lukas_Kastern

    Joined:
    Aug 31, 2018
    Posts:
    97
    I've made some modifications to the interpolation calculation of the time system. I basically took the interpolation time calculation which the FPS sample used. Here's the version for the 0.5 NetCode package https://pastie.io/uhnbtz.cs

    It looks a lot smoother to me than the inbuilt interpolation
     
    bb8_1 likes this.
  21. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    450
    I believe NetCode 0.6 might have solved the Server Client Prediction errors
     
  22. ChrisPie

    ChrisPie

    Joined:
    Mar 5, 2015
    Posts:
    31
    The interpolaton is "interesting" in 0.6. I put the data into csv to graph it in excel:
     

    Attached Files:

  23. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    We've made a couple of improvements to interpolation time stability since 0.6. I think the most important one is a bugfix in NetworkTimeSystem.cs. Around line 235, `subidiff -= subInterpolateTargetTick+subPredictTargetTick;` should be `subidiff -= subPredictTargetTick;`.
     
    PhilSA, skiplist, bb8_1 and 1 other person like this.
  24. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,129
    @timjohansson I see. Is that possible for u to backport the fix?
     
  25. ChrisPie

    ChrisPie

    Joined:
    Mar 5, 2015
    Posts:
    31
    @timjohansson Thanks for quick response. I tried it and while it is better, I feel it should be much smoother, since this is 60 ticks per second, on same machine - directly through LoopbackIpv4. Plotting the delta exaggerates errors, so I'm also including plot of absolute position Z value. Pretty wobbly, and you notice it when playing.
    edit: ok I'm not sure if you actually notice this. Difficult to compare to server's gizmo when editor does a performance spike every second.
     

    Attached Files:

    Last edited: Oct 8, 2021