Search Unity

Bug Fishnet and rigidbody jitter

Discussion in 'Multiplayer' started by smakis, Jan 16, 2024.

  1. smakis

    smakis

    Joined:
    Jan 18, 2023
    Posts:
    24
    Heyoo

    Unity 2022.2.13f1, URP.

    I'm using fishnets client prediction v2, and I've encountered some issues regarding jitter and rigidbodies. In the documentation it says to turn off interpolation and instead let fishnet handle it, but no matter what I do there is always some jitter involved.

    In the first video it's just a regular rigidbody being moved with this code when the right and left key is held.

    Code (CSharp):
    1. m_RigidBody.MovePosition(transform.position + (transform.up * m_MovementSpeed * (float)InstanceFinder.TimeManager.TickDelta));


    This object is not networked, and in the video you can see that it's moving smoother as the tick rate goes up (from 10 to 60 to 240), toggling interpolation on this object does not change anything (as you would expect since it's now fishnet handling the update loop).

    And this is when it's moved in fixed update with a timestep of 0.1 (10 tick rate) with unity handling the update loop, turning on interpolation makes the object completely smooth.



    For v1 there is an OfflineRigidbody script, I assume something similar is needed for v2? I tried turning v1 back on and went to the demo scene for v1, but with a tick rate of 10 it still jittered heavily (it looked the same as rigidbody with 0.1 timestep using regular unity physics without interpolation).



    As for network objects since they have a graphical object they are interpolated, but it doesn't seem to properly recreate the interpolation used by unity.

    In this video it's the client prediction v2 rigidbody demo scene, where I've removed everything from the model except the ball to make it easier to see. The recording makes look worse than it is, but still displays the issue.



    If you lock the camera to the players graphical object the object itself moves smoothly, however now the rest of the world is jittering in the same manner, which makes sense since the camera would mimic the jitter of the object it's following. In my case I've attached a MagicaCloth asset to my player and the flag would jitter while attached to the player along with the rest of the world, slightly detached from the player as the player would remain smooth. A stationary camera is the smoothest, but you can still see jitter as demonstrated in the video of the demo scene.

    If the camera has some form of smoothed follow instead the issues are exacerbated even more.

    Another clue is that the jitter is different depending on tick rate, where lower tick rates have weirder looking jitter where the rigidbody seems to catch up, while at really high tick rates the object looks a bit blurry instead due to the small but frequent updates.

    Regular interpolated rigidbodies using unitys fixed timestep would look the same as long as the timestep was low enough to not break physics.

    Some of the jitter in the videos can be explained by random spikes from the unity editor, but the problems remain even in builds.
     
  2. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    401
    Am I seeing and understanding correctly that this is also happening on clientHost and only with non-networked objects?
     
  3. smakis

    smakis

    Joined:
    Jan 18, 2023
    Posts:
    24
    All of this is on the client host, no connected clients. And it also happens with networked objects using v2 prediction, it's just much smaller jitter (see the video of the v2 rigidbody demo). Non predicted objects seem to have no interpolation at all.

    Objects moving at higher speeds have more obvious jitter, kinda like it over-interpolates back and forth (in the case of networked, predicted objects).

    edit: using fishnet 4.0.7, but has been an issue for a while
     
    Last edited: Jan 16, 2024
  4. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    401
    Got it. This isn't a bug so much as there is nothing interpolating the objects, as you know. You should not use interpolation on predicted objects but there should not be an issue doing so on non-predicted ones.

    I can make a monobehaviour script that utilizes our tick smoother class so it can be drag and drop.
     
  5. smakis

    smakis

    Joined:
    Jan 18, 2023
    Posts:
    24
    Toggling interpolation on non predicted objects has other issues however, see video of the red cube. This is 10 tick rate, a rigidbody with a mesh just falling from gravity, interpolation is on. It looks like it renders the cube both where it would be if the interpolation was on AND off at the same time.




    The main problem though is the jitter on predicted objects (even though offline rigidbodies without jitter would be nice), in the posted videos they do not have interpolation toggled, in all my tests with v2 prediction interpolation has been turned off (on the rigidbody).
     
  6. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    401
    Okay, I'll check it out. Using MovePosition or velocity on the RB shouldn't make a difference as it's not at all related to the interpolation. The only thing that matters is you have the graphicalObject set in the NetworkObject component (seen once ticking Enable Prediction).

    Non predicted objects do not have a smoother yet. I just wrote one, have to test it out, most likely tomorrow.
     
  7. smakis

    smakis

    Joined:
    Jan 18, 2023
    Posts:
    24
    Bless, I made two builds with different tick rates in order to record at a higher frame rate in case that helps visualize it better. Rigidbody v2 demo scene (with some slight adjustments for visibility and snappier movement).

    30 Tick rate.



    60 Tick rate.



    It's hard to tell but it should be visible. Obviously this is far from exact, but if I step frame by frame in the video sometimes the object does a much smaller adjustment than it should, that it then correct the next frame causing a visible stutter/jitter.
     
  8. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    401
    You mentioned using the prediction v2 rigidbody scene, but I noticed your level looks a little different so I assume you modified it. Did you try the demo scene as-is? When I run as host on both 10 and 60 tick rate I see absolutely no jitter using the scene as-is.
     
  9. smakis

    smakis

    Joined:
    Jan 18, 2023
    Posts:
    24
    Unmodified it's basically imperceptible, you can still see it from time to time but it's mostly hidden (I believe) by low velocities. It also seems to be happening more often on higher tick rates? Upping the move rate to 30 and setting the tick rate to 60 makes it a lot more apparent to me. In fact 30 move rate on 10 tick is a lot smoother than 30 move rate on 60 tick.

    edit: Try adding a moving camera as well, if it's still smooth for you at 30 move rate 60 tick and the camera has a smooth time then I don't really know what's going on in my project.
     
    Last edited: Jan 17, 2024
  10. victornor

    victornor

    Joined:
    Jan 17, 2014
    Posts:
    87
    I'll post my experience too. I'm having this exact same issue with jittering to different degrees depending on framerate and tickrate, when using smooth camera movement on both client auth and server auth (with CSP).

    Here is an example scene showing virtual camera with Aim: Composer at 20, 50 and 100 tickrate, as well as virtual camera with Aim: Do Nothing at 20, 50 and 100 tickrate respectively.
    I'm updating camera in LateUpdate.

    TLDR: Cinemachine virtual camera with composer aim at low tickrate has a lot of jitter on both client auth and server auth.


     
  11. victornor

    victornor

    Joined:
    Jan 17, 2014
    Posts:
    87
    Another video showing the issue in actual gameplay
     
  12. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    401
    Not quite the same thing. The camera jitter is an issue with virtual cams. I assume you are following the graphical object? If not have the camera follow that. If you are already following the graphical object try making another world object(no parent) to follow, and that world object follows the graphical in update. If that's smooth it could give some indicators of the problem.

    I'll try making the RB move faster to see if that changes anything.
     
  13. victornor

    victornor

    Joined:
    Jan 17, 2014
    Posts:
    87
    This is client authoritative, so there's no such graphical object (as in PredictedObject).
    But it's following what would be the graphical object.

    I have changed my test script to instantiate an empty object, which follows the networked object without being parented.
    Using this as follow target for the camera changes nothing.

    Code (CSharp):
    1. void Start()
    2.     {
    3.         _rigidbody = GetComponent<Rigidbody>();
    4.         _cameraTarget = Instantiate(_targetPrefab);
    5.    
    6.         GetComponentInChildren<CinemachineVirtualCamera>().Follow = _cameraTarget.transform;
    7.    
    8.         if (InstanceFinder.TimeManager != null)
    9.             InstanceFinder.TimeManager.OnTick += TimeManager_OnTick;
    10.     }
    11.  
    12.     private void Update()
    13.     {
    14.         _cameraTarget.transform.position = transform.position;
    15.     }
    Btw this seemed like the same issue to me, but maybe i'm having a different issue and i shouldn't be "stealing" this thread and instead create a new?

    Edit: It does seem like it's also the object jittering and not only the camera (so it's probably the same issue as smakis is experiencing). Using the TickSmoother as you said in discord makes no difference.
     
    Last edited: Jan 17, 2024
  14. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    401
    Definitely make a new thread please, this isn't the same thing. This isn't really a bug either, you just have to smooth the movement of the camera since you're moving within OnTick.
     
  15. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    401
    Are you on a 60Hz monitor by any chance? I had to turn down my refresh rate to 60Hz to see it, but I was able to!

    Try opening `BasicTickSmoother` and find this line...
    Code (CSharp):
    1. _graphicalObject.SetLocalProperties(_gfxInitializedLocalValues);
    Once found, simply comment it out. See if that helps.
     
  16. smakis

    smakis

    Joined:
    Jan 18, 2023
    Posts:
    24
     
  17. smakis

    smakis

    Joined:
    Jan 18, 2023
    Posts:
    24
    I'm on 144hz, but the game runs at 70-90 fps in the editor. It might differ from monitor to monitor and your hardware?

    After commenting that line out the player is silky smooth, like actually perfect. 100 % fixed. No jitter, no inconsistencies, the magica cloth flag is never jittering even if the camera is locked like it did before.

    The only weird thing now is that objects that are already in the scene when the game starts are offset from their physical representation, but I assume your suggestion was for debugging?

    upload_2024-1-17_21-19-44.png
     
  18. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    401
    Are those objects moving? If so are they rigidbodies?

    I'm not able to replicate this one so can you please provide me with as much information as possible.
     
  19. smakis

    smakis

    Joined:
    Jan 18, 2023
    Posts:
    24
    Absolutely. It's a networked predicted object just like the player, it moves but it's a passive one like described in the documentation, in my case it just applies buoyancy and gravity in the move function.

    The projectiles that you can shoot uses the same script, and has the same problem, these projectiles are instantiated and not part of the original scene. If I uncomment the line again they work as before (but jitter obviously returns).

    upload_2024-1-17_23-45-16.png
    upload_2024-1-17_23-45-30.png
     
  20. smakis

    smakis

    Joined:
    Jan 18, 2023
    Posts:
    24
    Tested a bit more and it seems to have something to do with the spawn position, if the object is at 0,0,0 it works just fine, if the object is at 0,40,0 the graphical representation is offset by about 48 or so below the physical object (and then retains that offset).
     
  21. victornor

    victornor

    Joined:
    Jan 17, 2014
    Posts:
    87
    Sorry for stepping in here again, but it does seem to me that my rigidbody is actually the cause of jittering and not my camera (which is set to update in LateUpdate).
    Basically the same issue as smakis was describing, but i'm not using prediction...
    You can see here that the camera is moving completely smoothly, but the cube is not.

     
  22. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    401
    It's not the same thing as one is related to prediction and the other is not. One could be more complex than the other, but both are relatively easy to fix with a few component adjustments. I'll have some new stuff in the next release which will resolve both so give me some time on that please :)

    I understand what you are saying but it's still not reproducing for me. Do you mind making a bug report on our github with a sample project? Here are instructions on that https://fish-networking.gitbook.io/docs/manual/guides/creating-bug-reports

    sample project guidelines specifically: https://fish-networking.gitbook.io/docs/manual/guides/creating-bug-reports#sample-project
     
    victornor likes this.
  23. smakis

    smakis

    Joined:
    Jan 18, 2023
    Posts:
    24
    Sure thing! I probably won't have time until tomorrow but I'll get to it as soon as I can. Worst case if there is something funky in my project I can either solve it myself or work around it, since restoring the local position of the graphical object manually after spawning the prefab fixes the issue.
     
  24. smakis

    smakis

    Joined:
    Jan 18, 2023
    Posts:
    24
    https://github.com/FirstGearGames/FishNet/issues/595

    I couldn't create a perfect repro, I suspect it's because the repro project being a lot simpler and the load is less heavy, however it should be close enough. The only difference is that the graphical object eventually self correct if you wait long enough, something that doesn't happen in my own project.

    edit: hitting the object with various stuff causing large movement shifts causes the graphics object to sync up, the larger the difference the more it interpolates to the correct position (in my own project, but the same thing probably happens in the repro).
     
    Last edited: Jan 19, 2024
  25. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    401
    Should be plenty help, thanks!
     
  26. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    401
  27. smakis

    smakis

    Joined:
    Jan 18, 2023
    Posts:
    24
    Sweet!

    I tried it and objects already in scene works perfectly now, however instantiated objects still seems to have some issues. If I shoot a projectile the graphics object follows, but rapidly falls behind the physics object, if I pause the game, cancel all velocities and then just let gravity move it it still happens. From what I can tell this doesn't happen to the object that was already in the scene when the game started.

    This also doesn't seem to take into account if an object is instantiated as inactivated, moved and then activated, in that case the graphics object is inited at the spawn location and start with an offset (in my use case I spawn the projectile early and then activate it a short while later to make sure it exists on all clients before firing, I just set the correct position right before activating it).

    I also wonder if pooled objects could pose an issue, is the BasicTickSmoother reinited in those cases?

    I'm throwing together another repro package, want me to update the previous issue or make a new one?
     
  28. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    401
    Does this second bug you describe happen without the snapping in PreTick commented out like before?

    And yes, you are correct about the initialization question. I actually did add something in but did not include it in the code I sent because I added a few new methods elsewhere to call the Deinitialize and wanted to keep what I gave you simple.
    Code (CSharp):
    1.         /// <summary>
    2.         /// Keeps initialized values but unsets runtime values.
    3.         /// </summary>
    4.         internal void Deinitialize()
    5.         {
    6.             _graphicalObject.SetLocalProperties(_gfxInitializedLocalValues);
    7.             _preticked = false;
    8.         }
    9.  
     
  29. smakis

    smakis

    Joined:
    Jan 18, 2023
    Posts:
    24

    The deinitialize makes sense, that would take care of the pooling problem.

    I don't quite understand the first part of your reply, do you mean before I tried with the new code you pasted in the issue comment? In that case no, the graphical object was offsetet (spawned in origo basically) and didn't interpolate towards the physical object, it behaved the same as the in scene objects which is why I didn't include projectile spawning in the repro (my bad).

    If you mean after the new code I'm not sure what line you are referring to, which line is the snapping line in pre tick? Or do you mean the line in the else in posttick?
     
  30. Punfish

    Punfish

    Joined:
    Dec 7, 2014
    Posts:
    401
    You said there is still a second problem. Did this second problem exist before we commented this out...
    Code (CSharp):
    1. _graphicalObject.SetLocalProperties(_gfxInitializedLocalValues);
    Either way, let me know and please attach a new project to the same issue.
     
  31. smakis

    smakis

    Joined:
    Jan 18, 2023
    Posts:
    24
    It did not, before the commenting it worked just fine (except for the jitter). But I finally managed to find the cause and a repro (not sure about the fix though), took me a while but eventually I realized that my projectile prefab had a scale smaller than 1 which seems to cause some funky math somewhere. Any scale above 1 works just fine (including projectiles in my own project). Updated the issue with repro.

    I realize that a scale smaller than 1 isn't recommended, but I guess it's an edge case that should be covered (or warned about).

    Not included in the repro (I really need to sleep) is the delay between spawn and activation. Would the deinitialize solve that, or is that just for pooled objects? In my case the projectile is spawned -> deactivated -> moved while inactive -> activated after about 0.1 seconds, which results in an offset projectile. Spawning a projectile and shooting it immediately works flawlessly.
     
    tmonestudio likes this.