Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Rotating a moving Rigidbody causes a stutter

Discussion in 'Physics' started by Dark-Protocol, May 20, 2017.

  1. Dark-Protocol

    Dark-Protocol

    Joined:
    Nov 19, 2011
    Posts:
    279
    Just before I start, let me say that I'm well familiar with how Update and FixedUpdate work and what Time.deltaTime and Time.fixedDeltaTime are all about.

    I have a simple physics-based player (an aircraft) which flies around using Rigidbody.AddForce in FixedUpdate (of course) and I rotate that aircraft by directly modifying its rotation in Update (using angularvelocity does not work for me, because I need the rotation to be custom). The problem is that whenever I try to steer my aircraft, I get a noticeable stutter in the motion because the rigidbody works in FixedUpdate and the rotation is done in Update.

    Everything would be solved now if I just put the rotation code in FixedUpdate, however, my aircraft's rigidbody is set to interpolate in order to smooth-out the movement over frames in case the framerate's higher than the fixed update step. In this case, having the rotation code in FixedUpdate causes the player to stutter even more and modifying the rotation in Update still creates a stutter even though the rigidbody is set to interpolate.

    Note that I'm not talking about camera jitter, the camera is parented directly to the object and not being controlled by anything so that the stutter can be seen clearly.

    So what I have so far is:

    FixedUpdate -> Movement with AddForce
    Update -> Rotate directly

    I tried to set the rigidbody's rotation in Update instead of the transform's rotation and that reduced the stutter a little bit but still not entirely.

    So how do you guys approach this problem? I'm not sure what else I can do.
     
  2. herb_nice

    herb_nice

    Joined:
    May 4, 2017
    Posts:
    170
    i have similar problems. the smoothest results i have found have been from turning OFF interpolation, and running the physics simulation once per render frame, with the clock as close to the render clock as possible. however, if your framerate fluctuates wildly, this will add error to your simulation.

    2017.1 has a feature where you can easily get rid of the whole fixed update sync pain, turning autosimulation off and putting Physics2d.Simulate(Time.deltaTime) in your update, completely removing the need for fixedudpate- and it's beauty stutter-free, but it's still quite crashy.

    back on unity 5.5.3 here since 2017.x and 5.6.x builds all fail longer soaks with crashy crash unity physics2d callstacks.

    If, like me, you can't rely on using 2017, the next best thing is to modulate Time.fixedDeltaTime in your update to trigger one fixed update per render frame, but this is far from accurate as the Simulate() method, will sometimes cause 2 simulation steps per frame, and sometimes none as your framerate changes, and your physics clock will drift from your render clock causing more jitter...

    i posted an example project in reply #10 of this thread where you can play with some of these ideas and compare results. https://forum.unity3d.com/threads/physics2d-autosimulation-false-is-the-greatest-thing.469867/

    if you find an even better way to synchronize physics, procedural animation, and rendering in unity, i am all ears. good luck!
     
  3. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,430
    @Dark-Protocol The correct path is modifying the rigidbody's rotation in FixedUpdate. This way the rigidbody will take care of the interpolation.

    However, you may still notice stuttering because both you and the physics are modifying the plane's rotation. This is the sequence of events:
    1. FixedUpdate: you modify rigidbody's rotation (Rigidbody.rotation).
    2. Internal Physics Update: the physics system takes the current rotation (yours), applies the rigidbody dynamics, and computes a new rotation.
    3. Internal Animation Update: object to be drawn receives the most recent value for the rotation, which is not the one you've set above.
    I'd better try applying a torque or angular velocity change based on the target rotation. Something like this in FixedUpdate (pseudocode for rotation around the Z axis):

    float delta = <compute difference among current rigidbody angle and the target angle you want to reach>
    rigidbody.AddRelativeTorque(Vector3.forward * delta * someFactor, ForceMode.VelocityChange);​

    Experiment with someFactor until you reach a value that does the work correctly. Most probably you'll have to use a small value here, as the velocity change happens in every physics frame.
     
  4. herb_nice

    herb_nice

    Joined:
    May 4, 2017
    Posts:
    170
    the problem @Dark-Protocol is describing also happens when you have objects that are not rigidbodies, but follow them. such as cameras, animated avatars, powerups, effects, etc. as soon as you get any degree of dependency things go to crap. they jitter like mad unless you update everything in fixed update- which means you need to crank your fixed update rate or they won't animate very fluidly....
     
  5. Dark-Protocol

    Dark-Protocol

    Joined:
    Nov 19, 2011
    Posts:
    279
    Thank you everyone so much for answering!
    I seem to have missed this but it sounds very promising. I think we can wait until 2017.1 comes out. So far the best solution for us has been, like @herb_nice said, to just turn off interpolation and handle everything in FixedUpdate. That way even if a high framerate of 200-300 FPS is achieved, what the player will observe will be movement with maximum of 75FPS (this is what the fixed time step is set to) but it gets rid of the jitter effectively and does not have error.

    @Edy As a matter of fact this is how I thought things would work too but if the rigidbody is set to interpolate and I modify the rotation of the rigidbody directly in FixedUpdate, I get quite some jitter. Adding torque is also not an option because I have some "keep upright" methods and also want to prevent collisions from adding torque to the airplane.
     
    ROBYER1 and Edy like this.
  6. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,430
    That depends on where your camera is being updated. If you're updating the camera in FixedUpdate (or it's attached to a rigidbody without interpolation enabled) then you'll have to handle everything else in FixedUpdate. If your camera is being updated at Update rate (as it should), then everything will be smooth if updated at Update (or based on a rigidbody with Interpolation enabled).

    That's what I described in the sequence of events: modifying the rotation of the rigidbody, no matter if it's interpolated or not, will cause glitches because the rotation will still be modified by the physics update, effectively overriding your rotation.

    Modifying the rigidbody's rotation works perfectly on kinematic rigidbodies only. Otherwise, there will always be some jitttering because both you and the physics are modifying the object's transforms explicitly. This is why a non-kinematic rigidbody should be modified via "physics": AddForce, AddTorque.
     
  7. herb_nice

    herb_nice

    Joined:
    May 4, 2017
    Posts:
    170
    if you update your procedural stuff in fixed update, it looks janky unless you run physics at full framerate. if you do it in update, you need to do your own interpolation for anything procedural, and unfortunately, you have to make guesses at where unity's fixed update time accumulator is at, so it is never going to be in sync. for example: http://answers.unity3d.com/questions/1119684/interpolating-between-fixedupdate-frames.html.

    box 2d is actually really fast and good. you can easily run one 2d physics step in a render frame if your scene not insane even on a 5 year old phone. fixed update adds jittery aliasing and complexity, and interpolation wastes cpu cycles and reduces accuracy. both of these things are old ideas from when physics performance just wasn't good enough.
     
  8. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,430
    My current approach for interpolation is using the latest two FixedUpdate states. As these are both consolidated states then you can be completely sure that the interpolated state goes from one to another in Time.fixedDeltaTime exactly. Interpolating these past states causes a small delay, as the current "physical" state will be ahead of the interpolated state. However, this delay is barely noticeable in most situations. In exchange you get a perfectly smooth visual movement at all situations.
     
  9. herb_nice

    herb_nice

    Joined:
    May 4, 2017
    Posts:
    170
    my game is twitchy so reducing latency in all ways possible is desired. however even that was not the case, the $10 question is: what's the deltaTime value you use to interpolate between the two cached frames?
     
  10. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,430
    (in Update)
    myDeltaTime = Time.time - Time.fixedTime;

    This is the time that has passed since the last FixedUpdate was executed. You can be sure that myDeltaTime will be not greater than Time.fixedDeltaTime.
     
  11. herb_nice

    herb_nice

    Joined:
    May 4, 2017
    Posts:
    170
    Thanks Edy. That looks similar to what I have tried before, but next time i play with the idea of interpolation i will give it a shot.