Kinematic rigid bodies does not move smoothly with MovePosition

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?

    using UnityEngine;

    public class JitterExample : MonoBehaviour
    {
     GameObject object1, object2, object3, object4;

     const int MOVE_SPAN = 5;
     const float SPEED = 2f;


     void Start()
     {
     object1 = GameObject.CreatePrimitive( PrimitiveType.Cube );
     object1.name = "Object1";

     object2 = GameObject.CreatePrimitive( PrimitiveType.Cube );
     object2.name = "Object2";
     object2.AddComponent<Rigidbody>();
     object2.rigidbody.isKinematic = true;
     object2.rigidbody.interpolation = RigidbodyInterpolation.Extrapolate;

     object3 = GameObject.CreatePrimitive( PrimitiveType.Cube );
     object3.name = "Object3";
     object3.AddComponent<Rigidbody>();
     object3.rigidbody.isKinematic = true;

     Camera.main.orthographic = true;
     Camera.main.orthographicSize = 5;
     Camera.main.transform.position = new Vector3( MOVE_SPAN * SPEED * 0.5f, 0, -5 );

     RenderSettings.ambientLight = Color.black;
     }


     void Update()
     {
     object1.transform.position = new Vector3( Mathf.PingPong( Time.time, SPEED ) * MOVE_SPAN, 2, 0 );
     }


     void FixedUpdate()
     {
     object2.rigidbody.MovePosition( new Vector3( Mathf.PingPong( Time.time, SPEED ) * MOVE_SPAN, 0, 0 ) );
     object3.rigidbody.MovePosition( new Vector3( Mathf.PingPong( Time.time, SPEED ) * MOVE_SPAN, -2, 0 ) );
     }


     void OnGUI()
     {
     GUILayout.Label( "WHAT YOU SEE" );
     GUILayout.Label( "\tObject 1: Moving by setting transform.position from Update." );
     GUILayout.Label( "\tObject 2: Moving by calling rigidbody.MovePosition from FixedUpdate (isKinematic+Extrapolate)." );
     GUILayout.Label( "\tObject 3: Moving by calling rigidbody.MovePosition from FixedUpdate (isKinematic)." );
     GUILayout.Space( 20 );
     GUILayout.Label( "QUESTION" );
     GUILayout.Label( "How to move a kinematic rigidbody smoothly?" );
     }
    }

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.

1 Like


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.

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).

3 Likes

Thanks for the response!

[quote]
if it is jerky, reduce the fixed time interval until it becomes smooth.
[/quote]
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!

[quote]
it's not all broken. You're just doing it wrong (tm).
[/quote]
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.

[quote]
frame-rate (by default 20 fps)
[/quote]
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

[quote=“cecarlsen”, post:5, topic: 480504]
Correct me if I’m wrong, but the default physics time step is 0.02 ms which is 1 / 0.02 = 50fps?
[/quote]

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.

[quote]
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
[/quote]
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

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?

[quote]
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?
[/quote]
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.

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.

rigidBody.velocity = Vector3.zero;
rigidBody.AddForce(speedVector,ForceMode.VelocityChange);

Thanks, but I need the rigid body to be kinematic.

[quote=“AngryAnt”, post:4, topic: 480504]
If you feel like writing a physics engine[…]
[/quote]

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#) :

Vector3 speed = new Vector3(5f, 0f, 0f);
void Update()
{
	Vector3 newPosition = rigidbody.position + speed * Time.deltaTime;
	rigidbody.MovePosition(newPosition);
}

But with this, I still get jittered movement. Did I understand something wrong too? :confused:

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.

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:

void Update()
{
      position = rigidbody.position + velocity * Time.fixedDeltaTime;
}

void FixedUpdate()
{
      rigidbody.MovePosition(position);
}

Hope that helps :)

6 Likes

its an old thread. so no not really.

Helped me, thanks for posting.

6 Likes

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.

1 Like

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.

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.

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.

1 Like