Search Unity

SmoothMovementTest, should help eliminating Hiccup sources

Discussion in 'Works In Progress - Archive' started by Marrt, Dec 16, 2012.

  1. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    Hi, dont know if this thread belongs here but it may be of interest for some people:

    i was tinkering around a bit with Unity's Rigidbody interpolation modes and wanted to create a little testing scene... i added some options for vsync and frame rate limitation... i was able to get a hiccup free movement (with vsync of course). Any thoughts or feedback on the topic of "smooth object movement" or this little package i made, are welcome :D

    $Capture.PNG

    Try it here:
    http://marrt.elementfx.com/index.html?file=SmoothMovementTest.unity3d

    or download the package V1.2:
    View attachment $SmoothMovementTest.unitypackage

    Original Thread that bugged me:
    http://answers.unity3d.com/questions/275016/updatefixedupdate-motion-stutter-not-another-novic.html


    Notes:
    don't expect smooth movement in standalone without vsync
    • single frames WILL be dropped and/or others WILL be shown for 2 screen cycles, this is very noticeable in my testsetup
    don't expect smooth movement in the editor, any time
    • various reasons i don't really know much about but who cares about editor smoothness anyway
    don't expect smooth movement in webplayer if the browser or VGA caps the framerate:ONLY expect smooth movement if the following conditions are met:
    • vsync is set to 1 (or 2 for every 2nd frame, but 2 will appear jerky even if no frames are dropped)
    • the framerate isn't capped below your screen refresh rate by any means (e.g. webplayer caps at 50 for me, so i only have smoothness when i manually set the screen refresh rate of my hardware screen <= 50)
    • the object or camera -position, is updated in Update. If your object has a rigidbody it will only change position in Fixed Update (if unity-interpolation doesn't work, try my manual interpolation)
     
    Last edited: Jan 14, 2014
  2. stfx

    stfx

    Joined:
    Jun 15, 2011
    Posts:
    7
    Its bad that nobody has replied so far since this is an important fix for an annoying issue.

    I can definately verify that the following helps reduce/fix jittery movement when applying manual transform and not being able to use rigidbody interpolation mode:
    Code (csharp):
    1. // extrapolate visual position based on position of rigidbody at last fixed update
    2. transform.position = MyRigid.position + MyRigid.rigidbody.velocity * (Time.time - Time.fixedTime);
    Say, do you also have a solution for rotation smoothing when not using force/torque since I dont really have velocity for that?

    Example:
    Code (csharp):
    1. _currentRotation = Quaternion.Euler(Vector3.Lerp(_currentRotation, targetRotation, lerp));
    2. transform.localRotation = _currentRotation;
    Thanks
     
  3. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    Hi, i also added manual interpolation in my implementation, maybe it can help you with your rotational stuff.

    if i am using vsync=1 i do interpolation otherwise extrapolation
    i cant exactly remember why i did this (did so much completely other stuff in the meantime) but i just quickly post what i currently do:
    the code for the interpolation looks like this:

    Code (csharp):
    1. //Info
    2. //shipModelTransform:   my rigidbodyless camera target
    3. //trueShipTransform:    my shipParent with a driven rigidbody and collider
    4. //previousPosition:     save previous position for interpolation in FixedUpdate, init can be Vector3.zero
    5.  
    6. //in Update()
    7. float lerpFactor = ((Time.time-Time.fixedTime)/Time.fixedDeltaTime);               
    8. if(extrapolate){
    9.     //extrapolation
    10.     shipModelTransform.position = trueShipTransform.position + ((shipRigidbody.velocity)*lerpFactor*Time.fixedDeltaTime); //
    11.     shipModelTransform.rotation = trueShipTransform.rotation;
    12.         //i dont do rotational extrapolation, but i you have to you should use Rigidbody.angularVelocity i guess
    13. }else{
    14.     //interpolation
    15.     shipModelTransform.position = Vector3.Lerp(previousPosition, trueShipTransform.position, lerpFactor);
    16.     shipModelTransform.rotation = trueShipTransform.rotation;
    17. }
    18.  
    19. //in FixedUpdate()
    20. previousPosition = trueShipTransform.position; //you would have to save the rotation too
    21.  
    i just rotate my ship in Update since it has a simple capsule collider and therefore rotational collisions can be neglected.
    if you rotate your object in FixedUpdate and want smoothness in Update... but without using angular velocity...

    then the interpolation case above should work for you but i haven't tested it sufficiently, please tell me if you succeed

    hope it helps

    EDIT: fixed code a bit, removed notes that made no sense in context
     
    Last edited: Jan 28, 2013
  4. stfx

    stfx

    Joined:
    Jun 15, 2011
    Posts:
    7
    Would be interesting to know why you are doing this since I am currently only using extrapolation since you dont need additional variables but maybe thats wrong.

    I just fixed rotation smoothing using extrapolation by calculating the angular velocity myself in fixed-update:

    Code (csharp):
    1. Vector3 newRotation = Vector3.Lerp(_currentRotation, targetRotation, lerp);
    2. _currentAngularVelocity = (newRotation - _currentRotation) / Time.deltaTime;
    3. _currentRotation = newRotation;
    4.  
    5. transform.localRotation = Quaternion.Euler(_currentRotation);
    Code (csharp):
    1. float extrapolationLerp = Time.time - Time.fixedTime;
    2.  
    3. // extrapolate visual position based on position of rigidbody at last fixed update
    4. _visual.localPosition = _currentPosition + _currentVelocity * extrapolationLerp;
    5. _visual.localRotation = Quaternion.Euler(_currentRotation + _currentAngularVelocity * extrapolationLerp);
    Anyway thanks for posting your solution. Helped a lot :)
     
    Last edited: Jan 28, 2013
  5. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    i think i did this by testing, getting the best results with interpolation when vsync was on.. otherwise everthing was jumpy
    But i noticed a mistake now, i set previousPosition in both, Update() FixedUpdate()... i updated my previous post, extra intrap. should be both usable in any vsync case now. But i currently have no access to my code and cant test it though.
     
  6. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    Hi, i added a few things and improved the UI

    -now includes both, inter- extrapolation
    -for position rotation
    -added physics-timestep slider

    check first post for source and webplayer, ignore all above code samples, they are implemented in it
     
    Last edited: Jul 8, 2013
  7. J_P_

    J_P_

    Joined:
    Jan 9, 2010
    Posts:
    1,027
    Thanks for this -- was building something similar so it's nice not having to reinvent the wheel.

    Ever figure out why the 60f was necessary?

    Code (csharp):
    1. cube.transform.rotation = cubeRigid.transform.rotation * Quaternion.Euler(cubeRigid.rigidbody.angularVelocity*lerpFactor*Time.fixedDeltaTime*60F);
    2. //quaternions (rotations) are aggregated by multiplying them. I have no idea why i need 60F at the end, but it seems to work with any frame rate
    I'm surprised by how bad it runs w/o vsync, at least on my iMac -- near constant tearing and movement wasn't even close to smooth. Will have to check other machines/games, but I usually play games with vsync disabled and don't notice nearly as much tearing or jitter.
     
    Last edited: Nov 1, 2013
  8. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    This is all overcomplicating things in my view. Best smoothness:

    //vsync on and...
    a += amount * Time.smoothDeltaTime;


    That does the trick just fine. Very smooth on all 6 tested devices/platforms. With vsync off, it handled very well still. Perhaps try smooth sometime, it might work for you.
     
  9. J_P_

    J_P_

    Joined:
    Jan 9, 2010
    Posts:
    1,027
    Sometimes things get complicated. Like if you need physics-based movement for a player, but also need mouselook. Unity's interpolation/extrapolation work for rigidbodies when you're moving/rotating them with forces, but not when you're manipulating them manually (like you'd typically do with mouselook). His custom interp/extrapolation would allow proper physics calculations in FixedUpdate but with smoothed movement and rotation in Update.
     
  10. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    i expect that Time.smoothDeltaTime will give bad results if the framerate varies greatly, but then smoothness would be bad anyway...

    long time has passed since i last looked into this issue, it seems that currently my web-build stays on 58 frames for some strange reasons (a single stutter every second).
    But standalone is perfectly smooth with 60... However, my main game (top down shooter thingy) is perfectly smooth even in web-player despite the camera being locked onto rigidbodies, maybe i should check the code for this testsetup again next year when i have time again.

    For me all the fuss was only about getting my camera hard-locked (no laggy smooth follow) onto my rigidbodies without stuttering, and for my little game it worked out... but Unity-Rigidbody-Interpolation should be working in the same way as my test-setup should show
     
  11. iddqd

    iddqd

    Joined:
    Apr 14, 2012
    Posts:
    501
    Hi Marrt, thanks for your research and the nice demo!

    I'm trying to get your custom extra-/interpolation working on the new Unity First Person Controller (which now has a rigidbody):
    https://www.assetstore.unity3d.com/#/content/14474

    The extrapolation seems to work, but the player then moves at double the speed, so i must be doing something wrong. Any ideas?

    Code (csharp):
    1.  
    2. // in Update()
    3. if(extrapolate)
    4. {
    5.      transform.position = rigidbody.position + ((rigidbody.velocity) * lerpFactor * Time.fixedDeltaTime); //
    6. }
    7.  
    8. // in FixedUpdate()
    9. previousPosition = rigidbody.position;
    10. // new velocity:
    11. rigidbody.velocity = desiredMove + Vector3.up * yv;
    12.  

    To test the jitter on the new FPS Controller, make the Run Speed higher (something like 30), Strafe around an Object while always looking at the Object.

    I am not using VSync.
     
  12. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    Hmm, why did you search for this solution? did you experience a visual stutter? i guess you have tried Unity's intergrated inter/extrapolation (dropdown at the rigidbody component) already?

    About the problem with double speed: Your rigidbody is tied to the transform you are extrapolating. Currently Unity applies the velocity-position-change in FixedUpdate(), and you apply an additional position change in Update(). In my Solution the Transform that is extrapolated has to be detached from your rigidbody, a seperate object without a rigidbody, only for visuals.

    In your case the "Transform" that has to be smooth is the Camera, so just get the camera detached from your rigidbody. Out of my head this would be the fix: just detach the camera, get a reference to its transform (in Start() yourCameraTransform = GameObject.Find("YourCameraName").transform) and modify its position:

    Code (csharp):
    1.  
    2. // in Update()
    3. if(extrapolate)
    4. {
    5.      yourCameraTransform.position = rigidbody.position + ((rigidbody.velocity) * lerpFactor * Time.fixedDeltaTime); //
    6. }
    7.  
    8. // in FixedUpdate()
    9. previousPosition = rigidbody.position;
    10. // new velocity:
    11. rigidbody.velocity = desiredMove + Vector3.up * yv;
    12.  
     
  13. iddqd

    iddqd

    Joined:
    Apr 14, 2012
    Posts:
    501
    Wow, thanks a lot for the fix.. It's working really smooth now - finally :)

    Yes, there is stutter and the integrated interpolation did nothing.
     
  14. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    Nice, good that this actually helped someone. I also would recommend using Interpolation rather than extrapolation, with extrapolation your camera could move through walls for one or two frame if you have fast movement and a small character collider.

    But it is really strange that Unity's Extra/interpolation doesn't work for you since its exactly the thing that they invented it for. I've made small testsetups where Unity's-Smoothing worked, in a gametest of mine however, it didn't work. Must have something to do with how much children the smoothed rigidbody-object has or something, i don't know.
     
  15. iddqd

    iddqd

    Joined:
    Apr 14, 2012
    Posts:
    501
    Thanks for the tip on inter/extrapolation, I'll do some testing.
    Well yes it's strange that unity's interpolation doesn't work in this case - i have no idea why.
     
  16. Manny Calavera

    Manny Calavera

    Joined:
    Oct 19, 2011
    Posts:
    205
    This hiccup/stutter problem seems to be a recurring topic in many threads and unity questions. This thread in particular appears to have made the most progress.

    The most basic example I can think of is by using Unity's 2D platform sample from the asset store.

    If you delete the tower and duplicate the bridge side by side like in the screenshot attached below and run left/right you can see the clouds in the background stutter (everything actually, but the clouds are easier to spot).

    Stutter.png

    Marrt, how would you go about applying your method to fix the Unity's sample?
     
  17. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    If you're doing any of this within the Unity editor and not standalone, then it will probably always have micro stutter (on windows). Must test standalone.
     
  18. Manny Calavera

    Manny Calavera

    Joined:
    Oct 19, 2011
    Posts:
    205
    I'm testing with a standalone build.
     
  19. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    Hi, i found some time and took a look at the build Unity offers, these are my quick thoughts, perceptions and a solution, please dont mind my dirty writing style, i wrote it while scripting this out:

    1. Info (blabla)
    2. Solution Info (blablablabla)
    3. Solution Source (skip above and just test those damn scripts)

    1. INFO:
    Yes, it is stuttering like S*** and the Unity-Interpolation doesn't do anything, why do they even release something like this??

    - 3 possible sources of the stutter: camera-movement-script, parallax-scrolling-script and the character-controlling-scripts

    Parallax script: Should be fine, it updates in Update()... but we keep in mind that the camera-script may be called before the scrolling-script, so we should set the camera Updater to LateUpdate() later.

    Camera Follow: uses Fixed Update, that means the camera re-positioning happens in physics frames, not in the render frames. We have to fix this! (-> put every "transform.position = ..." into Late Update and inter-/extrapolate the Rigidbody-position-input for the renderframes)

    Character Controller: The CharacterController is a script that sets the Characters velocity and applies forces, so everything in here is physic-engine dependent, nothing is setting positions directly, that's fine so far.
    We take a look at the Character Game Object and find that it has Rigidbody Interpolation enabled so if we access the transform position of that gameobject in Update(), it should appear smooth due to Interpolation (http://docs.unity3d.com/Manual/class-Rigidbody.html), but it isn't.

    2. SOLUTION INFO:

    Solution1. You could set the Camera to follow the interpolated rigidbody position (renderPos in script):
    -problem, rigidbodys will still jitter around like crap, try the source. In this source the Camera is pinned to the renderPos. I also edited the "TrackPlayer"-function because the smooth follow was messed up because it was tied to the jumpy rigidbody. In code, look for this to switch between inter or extrapolation, tracking mode is set via a bool flag:
    Code (csharp):
    1.  
    2. void LateUpdate (){  
    3.         //Choose Inter, or Extrapolation:
    4.         CameraInterpolation();
    5.     //    CameraExtrapolation();  
    6.  
    7.         //default track function, if you like it, set the trackFunction bool
    8.         if(trackFunction){TrackPlayerNEW();}
    9.     }
    10.  

    Solution2. You could detach the Rendered parts of the Rigidbody and move them independent to the renderPos from the rigidbody (you can also use this position as camera placement origin =Solution1). (Be aware that if the audio-listener is on the character and a renderObject has a 3D- Audio source on it, it could create weird stereo effects, move the listener to a renderObject).
    But detaching may be bad for some reasons or could interfere with existiing code that accesses childs. So you can also keep the Renderparts as children and only add an temporary Offset to them (reset this offset in the next frame because we get a new offset that is independent of tzhe first). Just gather all children in the Character that have an "Sprite Renderer" Component.

    Bonusblablabla: Basically Solution2 tries to give all visible parts of a rigidbody-gameObject a new position that is updated every render-frame instead of every physics-frame. Physic-frames have no timing-connection with render-frames. A Render-frame just samples the last rigidbody-position of the rigidbody - and this could happen twice between two physic-frames. The rigidbody-position is updated in FixedUpdate() and 2 Updates()calls could happen before the next FixedUpdate()call. Practical Example: If you have 50physic-frames/s and 60 render-frames/s(both very common values), about 10 positions per second would be sampled twice and jitter is introduced. Setting fixedTimestep to a value that yields 60 physic frames is also not a guaranteed jitter-kill since render-frames can vary greatly and you would have a double sample every once in a while.


    3. SOLUTION SOURCE:
    Solution1
    : replace "CameraFollow.cs" with this file and test the build, background will stop stuttering
    after that
    Solution2: additional to above, attach this component "SmoothRigidbodyRender.cs" to the hero (and or enemies) to stop the now visible rigidbody stuttering

    It is perfectly smooth in standalone, except the health bar that my scripts don't touch yet.


    *however, one problem remains with the scripts, i don't know anything about sprite animations and how they work but they seem to manipulate the actual localPositions of the sprites and reset them from time to time, so my script messes up those animations, i did a small workaround to disable animations. ... but if you create a child - within the RigidbodyObject - that holds the animation logic and all gameObjects that have SpriteRenderers, then you could set that child to renderPos and animations should still work...

    If you have any questions or problems to understand why we have jitter in the first place, just ask :D
     

    Attached Files:

    Last edited: Jul 14, 2014
  20. Manny Calavera

    Manny Calavera

    Joined:
    Oct 19, 2011
    Posts:
    205
    This is absolutely fantastic! I can confirm that applying both of these scripts together fixes the jitter in the Unity sample. Following the same approach I was able to fix my game as well.


    @Marrt, thanks for taking the time and sharing this with the community. You've just made the world a better place (or at least smoother).

    -1 to Unity for spreading bad coding patterns and +1 to @Marrt for fixing it.
     
    Marrt and dreasgrech like this.
  21. Apparaten_

    Apparaten_

    Joined:
    Jul 9, 2013
    Posts:
    45
    Dont mix up rotations and positionchanges with rigidbody/transform.
    If you are using a rigidbody don't use any transform commands use:
    rigidbody.moveposition
    rigidbody.rotation
    Etc...
     
  22. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    I havnt looked at the package, but are you using a kinematic rigidbody?

    Moving a collider (non-trigger) without a rigidbody is wrong.

    Moving a collider with a non-kinematic rigidbody via Translate/Rotate/.postion/.rotation is wrong.

    If youre not doing either of the above, thats fine, but if you are... well... start again.
     
  23. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    hmm, never used that method before :D , need to check it sometime soon, but i think it would definitely mess up the behavior if i constantly set the rigidbodyposition in Update() (can't do it in FixedUpdate if i want smoothness).

    I never directly set the position of any rigidbody/collider nor is it kinematic, the rigidbody/collider is completely unaffected.

    But my approach needs the rigidbody-game-object to have all renderers to be in children or seperate objects so it may require some manual restructuring of object hierarchies (yeah, that's bad). Then i just offset those visible children in a way to appear smooth. If you then pin your camera on a smooth child you completely eliminate all jittery effects.

    But isn't Unity's rigidbody-interpolation supposed to do something like this?

    Maybe there is a better way like just offsetting the renderers without changing transform.position of children, but i don't know. I only know that you perceive jittery things in Unity when you don't take care about it.
     
    Last edited: Jul 15, 2014
  24. Apparaten_

    Apparaten_

    Joined:
    Jul 9, 2013
    Posts:
    45
    Im not entirely sure why you need to change the position of childrens, I use interpolation and it works very good, the main rules you have to follow are these:

    If you want to change the position of a transform/go with a rigidbody attached, do it in FixedUpdate and do it by using rigidbody.position.
    if you want to change the rotation of a transform/go with a rigidbody attached, do it in FixedUpdate and do it by using rigidbody.rotation.

    dont mix things up, ex changing the position with transform.rotation and the position with rigidbody.position

    And dont forget to put it in fixed update!

    as a sidenote, i dont change the rigidbody.position when moving it, I use rigidbody.velocity(SpeedXYZ,ForceMode. VelocityChange) but i think rigidbody.position -changes would work too.
    as that works pretty similar as transform.translate. Interpolation is set on the rigidbody and it works perfect :)
     
    pietersmobile likes this.
  25. Manny Calavera

    Manny Calavera

    Joined:
    Oct 19, 2011
    Posts:
    205
    @Apparaten_ , have you tried running Unity's 2D platform sample from the asset store? I provided more details in my original post on this thread. Both myself and @Marrt experienced stutter while running that project. That's a very basic setup and it's provided by Unity so I expected things to work smoothly out of the box. But they don't.

    @Marrt 's approach successfully fixes the stutter. @Apparaten_, do you have another fix that can be applied to Unity's sample that could also fix the stutter? If so, please share. We're all very interested in getting to the bottom of this.
     
    Last edited: Jul 15, 2014
  26. 0tacun

    0tacun

    Joined:
    Jun 23, 2013
    Posts:
    245
    How would you solve this issue with root motion enabled in mecanim? My best shot was to set the Application.targetFrameRate the same as my FixedUpdate framerate. It reduced the visible stutter on the charakter very much, but it doesn't look as smooth as in other 3D games.
     
  27. Apparaten_

    Apparaten_

    Joined:
    Jul 9, 2013
    Posts:
    45
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class test : MonoBehaviour {
    5.  
    6.     Transform tr;
    7.     Rigidbody ri;
    8.  
    9.     float speed = 400.0f;
    10.  
    11.     // Use this for initialization
    12.     void Start () {
    13.         tr = GameObject.Find ("CubeRigid2").transform;
    14.         ri = tr.rigidbody;
    15.     }
    16.     void FixedUpdate()
    17.     {
    18.         testtest ();
    19.     }
    20.     void testtest()
    21.     {
    22.         ri.AddForce ((tr.right * speed * Time.deltaTime) - ri.velocity, ForceMode.VelocityChange);
    23.         if (ri.position.x > 12.0f)
    24.             ri.position = new Vector3 (-12.0f, 0.0f, 0.0f);;
    25.     }
    26. }
    added this to your scene marrty and added a copy of your CubeRigid, as long as interpolation/extrapolation is set on, it works nicely.

    perhaps im being stupid here I Dont know :p
     
  28. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    No, you're not stupid, thanks for your Input :D.

    Yes, my test scene works for Unity's built in Interpolation (it even has a toggle for that somewhere below Rigidbody :D). The whole point of this thread in the first place was to have a little check-build in order to test if Browsers are correctly generating a vsynced smoothness and to visibly witness what "smooth" means. (E.g. For me. my old Opera 12.16 creates a hickup every 60 frames on my non-Intel-Vga devices which is very visible with my testscene.)

    The Problem we are all making such a fuzz about is that sometimes (maybe we made an error in our physic manipulations, or some components conflicts with it or whatever) Unity interpolation simply does not work. It was the case for my top-down-shooter test setup, that's why i did my own interpolation that seems to work every time but requires a special object hierarchy AND it is the case with the 2D-Platformer.

    If you have time, i would ask you to check the 2D-platformer: https://www.assetstore.unity3d.com/en/#!/content/11228 . If you can give it smoothness without my cumbersome code, pls share it, i wan't to know what breaks Unity's interpolation.

    @0tacun i have no experience in animations or how parts of the ragdoll are moved, but positional changes of the whole character-game-object should be inter/extrapolateable
     
    Manny Calavera likes this.
  29. pietersmobile

    pietersmobile

    Joined:
    Jan 26, 2014
    Posts:
    11
    That fixed a big, hours long headache for me!

    I had an object flying with a rigidbody and colliders. Physics interactions like addTorque to rotate around different axis while maintaining forward motion would work like a charm but using transform.rotation or rigidbody.rotation would cause really annoying stutters (you could even hear the sound stutter).

    To test what you said i just changed update() to FixedUpdate() while using rigidbody.rotation and wham, working like a charm!!

    Tnx
     
  30. pietersmobile

    pietersmobile

    Joined:
    Jan 26, 2014
    Posts:
    11
    Hi Marrt,

    I don't know exactly what you where looking into but i tried the following on your test project:

    i cut everything under update and just pasted it to the beginning of fixed update: Both cubes now move in the same way without stuttering.
     
  31. Sekandagu

    Sekandagu

    Joined:
    Jul 13, 2012
    Posts:
    3
    Hey Marrt you seem to have figured this stuff out alot better than me, I have a character moving in Fixed Udate and the Camera follow / Mouse orbit stuff in LateUpdate. So when i move and rotate mouse at the same time the character is stable but the surrounding world stutters. If i rotate standing still no stutter , If i run withouth rotating camera no stutter. I get rid of all the stutter if i put all camera movement in FixedUpdate. But this is very unstable. Would really appreciate any advice (Been trying to find a solution for over 20 hours) thanks !.

    CameraController :

    FixedUpdate()
    {

    }

    LateUpdate ()
    {
    ManangeInput();
    CalculateDesiredPostion();
    UpdatePosition();
    UpdateRotation();
    }
     
  32. withstand

    withstand

    Joined:
    Aug 1, 2016
    Posts:
    1
    Marrt

    'Not every superhero wears a cape'

    You are a legend my friend. Your scripts took out all the jittery movement from my rigidbody and my cameraFollow script. You should have made the CameraSmoothFlow script xD.

    Am thankful to guys like you who take out time to write codes in such a way that noobs like us can undertsand.

    Thankyou so much :)
     
  33. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    Thanks man, i am no superhero but i consider wearing a cape.

    What breaks Unity's Rigidbody Interpolation (last time a checked was a year ago) is anything that sets the object's position or rotation manually. You must only ever manipulate the Object by using AddForce if you want to use Unity's Interpolation.

    Of course,
    this is not always possible, especially for rotations. But there are some mechanisms that allow you to do just that: PID-Controller. As I have engineering background i love these controllers. Yeah, this is not the best use case, but they are fun for me, here is an example:
    Code (csharp):
    1.  
    2. //PID variables
    3.     private    float    kP = 25.0F;
    4.     private    float    kI = 00.0F;
    5.     private    float    kD = 05.0F;
    6.     //private    float    maxCorrection    = 0F;
    7.  
    8.     private    Vector3    previousError    = Vector3.zero;
    9.     private    Vector3    integralError    = Vector3.zero;
    10.     private    Vector3    error;
    11.     private    Vector3 correction;
    12.  
    13.     private Vector3 PIDMovementForce(Vector3 target){
    14.         error        = target - thisRigid.velocity;
    15.         error.y        = 0F;//i dont use this control-direction and set it zero because it would counteract gravity
    16.         correction    = kP *error + kI *integralError + kD *(error - previousError);
    17.         previousError = error;
    18.         return correction;
    19.     }
    20.  
    Use it like that in FixedUpdate, target is the speedVector you want the target to have.
    Code (csharp):
    1. Vector3 force = PIDMovementForce(target);
    2. thisRigid.AddForce(force, ForceMode.Force);
    3.  

    My Interpolation is just more forgiving because it uses either:
    - interpolation between the last position, so it is always a little bit behind the actual collider
    - extrapolation where it checks your current speed, this can be jumpy if you instantly change your speed

    What does "a little bit behind" mean?
    Example-pic for interpolation:
    The green capsule is the Collider at 50Hz (physics), the sprite is the visual interpolated to 60Hz (screen refresh) so the background scrolls super smoothly and the character is not jittering either
    Animation2.gif
     
    JamesArndt likes this.
  34. anasiqbal

    anasiqbal

    Joined:
    Jul 29, 2015
    Posts:
    6
    Hi,
    First of all thanks to @Marrt for this wonderful thread, I have searched alot for this problem and this thread is the closet thing I can find.

    I am working on a game project for iOS and android, and am having a similar Jitter problem. I have setup test scenes (in both 2D and 3D for testing purpose) with objects (non-rigidbodies) and orthographic camera. The camera is static and the objects move linearly. I have also tried the opposite where the objects are static and the camera moves. One thing to note is that in my case the player movement itself does not appear jittery due to which I have removed the player from the scene. So the test scenes only consist of a camera and very simple environment elements.

    To exlpore further I have also setup a test 2D scene which consist of square sprites moving across the scene.

    Objects have a simple movement script using "transfrom.Translate()" method to move linearly. I have tried vSync but it is no good specially on iOS (though the behavior is almost the same on Android). We have tried using "Update", "FixedUpdate" and "LateUpdate" but the problem persists.

    There are options to switch between the different update method:
    ScreenView.png

    And following is the code behind other options (i.e. Delta Time, Smooth Delta Time and Fixed Value):
    Code (CSharp):
    1. // Delta Time
    2. transform.Translate(Vector3.right * -1 * moveSpeed * Time.deltaTime, Space.World);
    3.  
    4. // Smooth Delta Time
    5. transform.Translate(Vector3.right * -1 * moveSpeed * Time.smoothDeltaTime, Space.World);
    6.  
    7. // Fixed Value
    8. transform.Translate(Vector3.right * -1 * moveSpeed * 0.02f, Space.World);
    Here is the scene setup preview. All the environment objects are children to "GeneratedSegmentParent" object and the movement script is attached to this parent object.
    SceneSetup.png

    I am sharing an android build since it is easier to distribute. Here is a link to a ".apk" file for reference of what we have tried. Please have a look and let me know if there is anything I am missing or is there anything else that can be done.
     
  35. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    I don't really understand what is jittering, if the camera is static, and the player doesn't jitter, what jitters then?

    I suspect your camera is, you need to think about the execution order https://docs.unity3d.com/Manual/ExecutionOrder.html
    Does your camera request the player position AFTER it has been updated for this frame? Simply put: You should move the player in Update() but camera in LateUpdate().

    If you already do you have to be more specific what exactly jitters, the background? the characters? are there Rigidbodies anywhere?
     
    JamesArndt likes this.
  36. anasiqbal

    anasiqbal

    Joined:
    Jul 29, 2015
    Posts:
    6
    Yes the player is moving in Update and the camera follows in LateUpdate.

    The Background is Jittering and no we are not using Rigidbodies anywhere.

    Since last post, we have been doing some research and it seems like the the issue is with the difference between Frame Rate and Screen Refresh Rate. We have tried fixing the required frame rate but it is not much of a help either. Please take a look at the following LINK as a reference.
     
  37. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    I have downloaded your .apk and tested it. At the beginning it is smooth, then hiccups occur every once in a while.

    Add a frame rate counter to your build. I now suspect that your framerate isn't constant.
     
  38. anasiqbal

    anasiqbal

    Joined:
    Jul 29, 2015
    Posts:
    6
    Thank You for taking out some time and testing the build.

    I have displayed both Frame Rate and screen refresh rate counter. And the app maintains a 60 fps (device refresh rate is also 60Hz). I also ran profiler on the app but there were no major spikes (Which is causing me headache as I cannot find any reason for these hiccups). I have check the unity stats for Set Pass Calls but it is also very low with an average of 7 (min 5 - max 8).

    Also, in the build you are testing, the elements do not even have any colliders or triggers. So it is just some very simple geometry using Vertex colours.

    Let me know if you need any other information. I can provide you a new build with fps and refresh rate counter if you want.
     
  39. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    If your framerate stays a perfect 60 even after the hiccup occured it can only be your transform manipulation. But is still think this is a framerate issue, try to measure the average frame-rate with at least 2 decimal places, so a single dropped frame will be noticed. You can also add a timer that counts realTimeSinceStartup to check if a frame had a considerable delay.

    The last thing: I could imagine that this could also be a garbage-collection issue that only causes hiccups on the mobile device, but not in editor (editor is never smooth to begin with, there are always hiccups in play mode, for me at least). But i am a noob concerning garbage collection diagnosis.
     
  40. Demonarchy

    Demonarchy

    Joined:
    Apr 19, 2018
    Posts:
    2
    For the ones who are still struggling with camera stutter in 2018, this is yet the best solution to stay with!
    I got nice improvements in a 3rd person shooter camera.

    If you are a bit overwhelmed bear in mind this key components for better understanding of the code:
    LerpFactor - Important!
    No-mesh parent GameObject with Rigidbody - Important!
    Child GameObject with the desired Mesh - Important!
    Parent previousPosition / previousRotation - Important!

    The magic takes place by lerping the mesh(child) from parent's previous transform to the current one. The lerpFactor varies constantly to fill the gap between Update and FixedUpdate making the mesh move fluently.
    Then you simply make your Camera follow the child in LateUpdate. That worked for me.

    Thanks @Marrt for this old but yet useful post
     
    Marrt and iddqd like this.
  41. FranciscoGuzman

    FranciscoGuzman

    Joined:
    Sep 10, 2019
    Posts:
    1
    a += amount * Time.smoothDeltaTime;

    This works in Unity 2019 - make sure to use Update(). I must have tried dozens of combinations of settings and this finally resulted in smooth linear kinematic motion. This also works with transform.Rotate().
     
  42. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    613
    I don't think this applies to Rigidbody-Physics.
    The Problem most people have is that they want to drive a camera by a PlayerObject which is using Physics. If they then manipulate the PlayerObject by anything other than Physics.AddForce(), Unities Interpolation will break and somthing (background or player) will jitter.