Search Unity

Kinematic rigid bodies does not move smoothly with MovePosition

Discussion in 'Scripting' started by cecarlsen, Jul 5, 2012.

  1. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    518
    I'm about to write my own physics instead of using the build-in system because of this. Quick responses are highly appreciated.

    EXAMPLE
    Copy the script below and attach it to a plain GameObject in an empty scene.

    WHAT YOU SEE
    Object 1: Moving by setting transform.position from Update.
    Object 2: Moving by calling rigidbody.MovePosition from FixedUpdate (isKinematic+Extrapolate).
    Object 3: Moving by calling rigidbody.MovePosition from FixedUpdate (isKinematic).

    Object 1: Moves smoothly.
    Object 2: Moves not so smoothly.
    Object 3: Moves like my grandmother.


    QUESTION
    How to move a kinematic rigidbody smoothly? Is it possible at all in Unity? And if not, why?

    Code (csharp):
    1.     using UnityEngine;
    2.  
    3.     public class JitterExample : MonoBehaviour
    4.     {
    5.      GameObject object1, object2, object3, object4;
    6.      
    7.      const int MOVE_SPAN = 5;
    8.      const float SPEED = 2f;
    9.      
    10.      
    11.      void Start()
    12.      {
    13.      object1 = GameObject.CreatePrimitive( PrimitiveType.Cube );
    14.      object1.name = "Object1";
    15.      
    16.      object2 = GameObject.CreatePrimitive( PrimitiveType.Cube );
    17.      object2.name = "Object2";
    18.      object2.AddComponent<Rigidbody>();
    19.      object2.rigidbody.isKinematic = true;
    20.      object2.rigidbody.interpolation = RigidbodyInterpolation.Extrapolate;
    21.      
    22.      object3 = GameObject.CreatePrimitive( PrimitiveType.Cube );
    23.      object3.name = "Object3";
    24.      object3.AddComponent<Rigidbody>();
    25.      object3.rigidbody.isKinematic = true;
    26.      
    27.      Camera.main.orthographic = true;
    28.      Camera.main.orthographicSize = 5;
    29.      Camera.main.transform.position = new Vector3( MOVE_SPAN * SPEED * 0.5f, 0, -5 );
    30.      
    31.      RenderSettings.ambientLight = Color.black;
    32.      }
    33.      
    34.      
    35.      void Update()
    36.      {
    37.      object1.transform.position = new Vector3( Mathf.PingPong( Time.time, SPEED ) * MOVE_SPAN, 2, 0 );
    38.      }
    39.      
    40.      
    41.      void FixedUpdate()
    42.      {
    43.      object2.rigidbody.MovePosition( new Vector3( Mathf.PingPong( Time.time, SPEED ) * MOVE_SPAN, 0, 0 ) );
    44.      object3.rigidbody.MovePosition( new Vector3( Mathf.PingPong( Time.time, SPEED ) * MOVE_SPAN, -2, 0 ) );
    45.      }
    46.      
    47.      
    48.      void OnGUI()
    49.      {
    50.      GUILayout.Label( "WHAT YOU SEE" );
    51.      GUILayout.Label( "\tObject 1: Moving by setting transform.position from Update." );
    52.      GUILayout.Label( "\tObject 2: Moving by calling rigidbody.MovePosition from FixedUpdate (isKinematic+Extrapolate)." );
    53.      GUILayout.Label( "\tObject 3: Moving by calling rigidbody.MovePosition from FixedUpdate (isKinematic)." );
    54.      GUILayout.Space( 20 );
    55.      GUILayout.Label( "QUESTION" );
    56.      GUILayout.Label( "How to move a kinematic rigidbody smoothly?" );
    57.      }
    58.     }
     
  2. Games-Foundry

    Games-Foundry

    Joined:
    May 19, 2011
    Posts:
    632
    At first glance you appear to be comparing apples with oranges. Update() is called each frame, which might be 100FPS for example. FixedUpdate ( and the physics cycle ) runs at a fixed interval ( under the Time settings ) independent of the frame rate, and may be running at around 30FPS. So in this scenario animations driven in Update would be smoother. Reducing the fixed time period to ( 1/60s = 0.016667 ) will result in FixedUpdate being called more often.

    For a better comparison, move your object1.transform.position code to be under FixedUpdate. Then, if it is jerky, reduce the fixed time interval until it becomes smooth.
     
    Last edited: Jul 6, 2012
    ahungrybear likes this.
  3. Morning

    Morning

    Joined:
    Feb 4, 2012
    Posts:
    1,141
    That's why you multiply movement speed by deltaTime.
    If you move character from fixed update, the speed would change if you decided to change your physics time in mid-development.
     
  4. AngryAnt

    AngryAnt

    Keyboard Operator Moderator

    Joined:
    Oct 25, 2005
    Posts:
    3,042
    If you feel like writing a physics engine you expect to outperform PhysX, please don't let me stop you. I bet it would be a very rewarding experience.

    However if you just want to solve the project at hand, use MovePosition or transform.position modifications each frame for smooth application.

    The only reason to use FixedUpdate for anything is when you need to instruct the physics engine to do something or query it at a regular interval.

    The physics simulation is not solved each frame, but at a lower frame-rate (by default 20 fps). With that in mind, realise that doing your force calculations or simulation monitoring at a higher framerate than the physics simulation would be pointless - since the simulation will not change before the next physics step (interpolation of existing forces aside). That is the point of FixedUpdate.

    When you make a rigidbody kinematic you are basically telling PhysX that you'll be handling the movement of this hierarchy, but that any colliders in it should be considered dynamic. Therefore you have no interpolated force calculations and you have no use for FixedUpdate. Like any non-rigidbody object you should move it each frame for smooth movement.

    Now whether to use MovePosition or modifying transform.position all depends on the behaviour you want.

    MovePosition will actually drag the colliders of the rigidbody along the path from their current position to where they would end up - pushing other colliders on the way.

    Directly modifying transform.position effectively teleports the hierarchy to the new position - at which point any overlapping colliders will get pushed out. At high framerates this behaviour makes transform.position modification virtually indistinguishable from MovePosition calls.

    So it's not all broken. You're just doing it wrong (tm).
     
    gauravkumar37 likes this.
  5. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    518
    Thanks for the response!

    Ah! I was wondering if I could do that – but I could not find the setting in the scripting reference so I assumed that it was impossible to do. I found the Time Manager panel and it fixed the issue. Thanks Games Foundry dude!

    I hoped someone would tell me so =)

    The kinematic rigid body drags other rigid bodies around, connected through configurable joints, so I need to update the position in FixedUpdate otherwise (as you also state) the transform is teleported. Anyway, I appreciate your explanation.

    Correct me if I'm wrong, but the default physics time step is 0.02 ms which is 1 / 0.02 = 50fps?

    Thanks again!
    ~ce
     
  6. AngryAnt

    AngryAnt

    Keyboard Operator Moderator

    Joined:
    Oct 25, 2005
    Posts:
    3,042
    You're absolutely right. Not sure where I started thinking we were running at 20fps.

    Regarding adjusting the fixed time interval just to smooth out some movement, I would really advice against it as it effectively kicks PhysX into high gear which you will feel on performance.
     
  7. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    518
    Smooth movement can't be compromised in the "game" I am currently working on. I've been fiddling with this for a while now. Decreasing the fixed time step seems to be the only way to get the desired behaviour.

    Thanks again.
    ~ce
     
  8. Futurerobot

    Futurerobot

    Joined:
    Jul 13, 2011
    Posts:
    179
    Just wondering. Won't extrapolate give weird results when using moveposition? If the rigidbody doesn't really have a speed then how does extrapolating the position work? Have you tried interpolate?
     
  9. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    518
    As illustrated in the example above setting interpolation to "Extrapolate" does reduce jitter slightly when moving a kinematic rigid body. My guess is that Unity tires to calculate the current position (at the time when Update is called) from the last positions handed to MovePosition in FixedUpdate, but I don't know for sure. Setting interpolation to "Interpolate" gives worse results.
     
  10. Futurerobot

    Futurerobot

    Joined:
    Jul 13, 2011
    Posts:
    179
    You didn't mention why the rigidbody is kinematic, but in case it's because you want to control the movement more directly, I went for a different solution in the end. I had some issues with movePosition myself, and got the tip to use Addforce instead. with the "ForceMode.VelocityChange" option, you basically tell it to add a set speed. Interpolate seems to work well with it.

    Each fixedUpdate I zero the previous speed and add a new one.

    Code (csharp):
    1.  
    2. rigidBody.velocity = Vector3.zero;
    3. rigidBody.AddForce(speedVector,ForceMode.VelocityChange);
    4.  
     
  11. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    518
    Thanks, but I need the rigid body to be kinematic.
     
  12. Spidyy

    Spidyy

    Joined:
    Mar 6, 2011
    Posts:
    184
    Hey AngryAnt,

    I'm bumping the thread because I encounter the same problem, and if I follow your explanation, the logical things to write to have both smooth movement and a good physics with kinematic rigidbody collinding anything in its route would be (in C#) :
    Code (csharp):
    1.  
    2. Vector3 speed = new Vector3(5f, 0f, 0f);
    3. void Update()
    4. {
    5.     Vector3 newPosition = rigidbody.position + speed * Time.deltaTime;
    6.     rigidbody.MovePosition(newPosition);
    7. }
    8.  
    But with this, I still get jittered movement. Did I understand something wrong too? :/
     
  13. Razieln64

    Razieln64

    Joined:
    May 3, 2008
    Posts:
    129
    I have a non kinematic rigidbody that I move around using forces and with interpolate set to "interpolate" it works fine. I use AddRelativeTorque to turn it around its pivot point when using a gamepad and AddRelativeForce moving it around.

    Now my problem is with the accelerometer of a touch based device. I need it to be mapped almost 1:1 so at the moment I'm directly setting the rigidbody's rotation thru the MoveRotation method. I haven't checked it yet on the profiler but I believe it spikes.

    My question is: how can I control the rotation of a non kinematic rigidbody directly without breaking physX? This is only for the rotation because I still want to keep using forces to move it around.
     
  14. Tu-Dinh

    Tu-Dinh

    Joined:
    Dec 12, 2012
    Posts:
    7
    I just have a similar problem, the I found a very simple solution. I update new position value in the Update, and call MovePosition with that new position in the FixedUpdate. Something like this:

    Code (csharp):
    1. void Update()
    2. {
    3.       position = rigidbody.position + velocity * Time.fixedDeltaTime;
    4. }
    5.  
    6. void FixedUpdate()
    7. {
    8.       rigidbody.MovePosition(position);
    9. }
    Hope that helps :)
     
    mayo_f, Juxta, Houp and 1 other person like this.
  15. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,618
    its an old thread. so no not really.
     
  16. timothyallan

    timothyallan

    Joined:
    May 22, 2013
    Posts:
    72
    Helped me, thanks for posting.
     
  17. MisterMashu

    MisterMashu

    Joined:
    Oct 23, 2012
    Posts:
    4
    If a rigidbody is kinematic, you should use transform.position instead of rigidbody.position, and use Update() instead of FixedUpdate(). I just spent a ton of time messing around with this and this is by far the best solution for me. Even with just a single object in my test scene, trying to move a kinematic rigidbody with the rigidbody.position (or rigidbody.MovePosition()) caused huge lag spikes constantly.
     
    killerjim likes this.
  18. AngryAnt

    AngryAnt

    Keyboard Operator Moderator

    Joined:
    Oct 25, 2005
    Posts:
    3,042
    Direct position updates in FixedUpdate not being smooth is expected - as described earlier in the thread.

    If moving your kinematic rigidbody with MovePosition or rigidbody.position, in a super simple scene, causes performance problems, please log that as a bug right away.
     
  19. funshark

    funshark

    Joined:
    Mar 24, 2009
    Posts:
    225
    MisterMashu > If you do that, and if I understood well ( in box2D at least ), the collision/trigger detections will have issues.

    AngryAnt > We can't be sure that it is performance problems; the thing is, moving a rigidbody (2D) with MovePosition, Velocity, or translate in FixedUpdate result in a less smooth movement than a translate in Update. And it seems no one has a good fix for that.
     
  20. AngryAnt

    AngryAnt

    Keyboard Operator Moderator

    Joined:
    Oct 25, 2005
    Posts:
    3,042
    Regardless of which direct position update codepath you use, as well as 2- or 3D context, applying them in FixedUpdate will *always* result in choppy updates. As outlined earlier in the thread, FixedUpdate is not invoked every frame, hence your object will stay in place for X rendered frame before it gets another position update in the next FixedUpdate invocation.

    Setting velocity in FixedUpdate should however not result in choppy movement. If you're seeing choppy movement in that scenario and you have confirmed a smooth velocity value input, that is a bug which should be reported.
     
  21. funshark

    funshark

    Joined:
    Mar 24, 2009
    Posts:
    225
    AngryAnt > what do you mean by "a smooth velocity value input" ? I'm speaking about a simple case when you move an object ( kinematic rigidbody ) from A to B linearly
     
  22. AngryAnt

    AngryAnt

    Keyboard Operator Moderator

    Joined:
    Oct 25, 2005
    Posts:
    3,042
    In that case, I'm guessing that you're setting a constant velocity value. Which would indeed be smooth.
     
  23. funshark

    funshark

    Joined:
    Mar 24, 2009
    Posts:
    225
    Setting velocity gave the same results as with movePosition.
    But maybe it is less expensive ( and more precise? ) than updating the position each fixedUpdate.

    The only ways to "smooth" things are :
    - setting a higher refresh rate in fixed TimeStep ( but not recommended )
    - activate interpolate on the rigidbody
     
  24. AngryAnt

    AngryAnt

    Keyboard Operator Moderator

    Joined:
    Oct 25, 2005
    Posts:
    3,042
    MovePosition does what it says on the tin. It sets the current position of the rigidbody *this very instant*.

    Velocity sets the velocity at which the physics engine should *continuously* move the rigidbody.

    I'm not sure which other words I can use to keep saying the same thing.
     
    Juxta likes this.
  25. funshark

    funshark

    Joined:
    Mar 24, 2009
    Posts:
    225
    You can move something continuously with movePosition too. I don't understand what you're trying to explain here.

    The fact is, either using movePosition on each fixedUpdate OR using velocity assignment, the result ( visually ) is the same.
     
  26. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,618
    lol!
     
    Juxta likes this.
  27. Juxta

    Juxta

    Joined:
    Sep 28, 2014
    Posts:
    4
    What AngryAnt is trying to say is FixedUpdate + MovePosition will result in choppy movement because you're teleporting objects around at a slower frame rate than "fluid motion". Just because you're "blinking" really fast and it appears smooth if tweaked really well, you're still dragging an object in very small "jerks" that are going to appear, well... "jerky".

    I've never seen the physics engine produce jerky movement on a rigidbody when assigned a velocity in FixedUpdate. Can you provide a simple example of that? In attempting to do so I suspect you'll find your problem...
     
  28. funshark

    funshark

    Joined:
    Mar 24, 2009
    Posts:
    225
    Sure, just assign a velocity to a 2Drigidbody object ( a big one, so you can really see the movement ).
    Set your vsync ON ( not sure it is necessary )
    don't activate interpolation :)

    Don't get me wrong.
    The solution IS to activate the interpolation ( interpolate ), but in doing so, it can bring some behaviours issues.
     
  29. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    200
    It's incredible how everyone says something different about this subject. I just need a clear answer on this...

    If I want a 2D element with a boxcollider and a kinematic rigidbody to constantly follow an npc for example what would be the correct way to do this?

    Fixedupdate causes jerky motion obviously cause the camera refreshes alot faster then fixedupdate, but from what I understand if an item has a rigidbody that requires movement it's advised to move it through the rigidbody.

    So what do I do here?
     
  30. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,125
    If you're using physics to move, do that in FixedUpdate, and set the body to interpolate or extrapolate. That means if you're moving the thing by setting it's velocity, or adding force.

    If you're setting the position, or translating the transform (which is a different way of setting the position), move it in Update.


    The only way you get smooth movement in FixedUpdate is through interpolation or extrapolation. Those essentially mean "assume that the rigidbody will keep moving approximately in the same direction with the same velocity until the next fixed update". If you're setting the position of the rigidbody, though, it doesn't have velocity. You're just teleporting it very often.
     
  31. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    200
    Well that's basically my question, should I be using physics to move it?

    It's a label that follows an item but I also need a boxcollider and a rigidbody to detect trigger events.

    Problem is once there's like a 100 or so rigidbodies moving every frame by setting the transform.position, the fps starts to drop alot.
     
  32. killerjim

    killerjim

    Joined:
    Sep 14, 2016
    Posts:
    10
    I came to this thread because I saw RigidBodies jittering around (I'm transferring them over a network and interpolate in my own code) - I tried FixedUpdate(), changing the order in which I sent, update, etc. them..

    The issue was around using rb.position in Update() as my RB's are kinematic.. You have to use rb.transform.position to get smooth movement, otherwise it looks like the humanoid is only updates the RB's every 5 to 10 frames (so it stutters.. )

    Thanks for this solution, works perfectly now!!