Different delta from transform.position versus rigidbody.position

I’m working on a kinematic platformer controller, and I’m trying to puzzle my way through some oddities in the physics.

So, I have a moving platform that simply moves up and down on the y axis. It moves by directly setting the rigidbody position in FixedUpdate

rBody.position = (Vector2.Lerp(lerpStart, lerpTarget, AnimCurves.easeInOut.Evaluate(lerpTime)));

Afterwards, the delta is calculated at the end of FixedUpdate

        xPosLastFrame = xPosThisFrame;
        xPosThisFrame = rBody.position.x;
        amountMovedX = xPosThisFrame - xPosLastFrame;

        yPosLastFrame = yPosThisFrame;
        yPosThisFrame = rBody.position.y;
        amountMovedY = yPosThisFrame - yPosLastFrame;

        delta = new Vector2(amountMovedX, amountMovedY);

Later, while testing, I decided to calculate the transform’s movement delta in Update

        trLastFramePos = trThisFramePos;
        trThisFramePos = transform.position;
        trDelta = (trThisFramePos - trLastFramePos);

To my surprise, the values are different!

I placed a print at the start of Update and FixedUpdate, so I can see that they’re both running in sync (there is one FixedUpdate being called for every Update). The platform is set to Kinematic, so it shouldn’t be influenced by any other objects.

Now, I realize these numbers are very close - but they should be identical, shouldn’t they? Is this assumption correct?

Granted, it turned out that my problem wasn’t related to this 0.0001 discrepancy - no surprise there - but I’m wondering if this discrepancy is a natural result of floating point math, or a result of the physics engine’s non-determinism, or if I legitimately ticked a wrong box somewhere and I’m getting unexpected results (this is my main worry).

Use the Rigidbody2D.MovePosition method instead. This is the only way interpolation is supported otherwise you’re just instantly teleporting it.

Not sure how you’re verifying that unless you can guarantee the frame-rate is the same as the fixed-update always or you’re running physics per-frame in which case you don’t need FixedUpdate.

If you are using interpolation then there’s a difference between the body pose and the transform pose because the transform pose is updated per-frame fromt he last pose to the current pose.

Beyond that, no idea what you’re doing. Yes, 0.0001 is a tiny distance (0.1mm).

The physics engines non-determinism IS due to floating-point and nothing whatsoever to do with what the physics system is doing. It’s the same non-deterministic as any of your other long-running float calculations.

Also, the physics system isn’t doing anything at all to modify the body pose if all you’re doing is setting the body pose directly and it has no velocity. All that happens is that after the physics set, the body poses are written to the Transform pose.

1 Like

I used to do this, but it appears that the change doesn’t occur until the next frame, right? https://docs.unity3d.com/ScriptReference/Rigidbody2D.MovePosition.html

So it seemed like it would cause more confusion. The Kinematic Controller tutorial modifies the position property directly, so I just went with that https://learn.unity.com/tutorial/live-session-2d-platformer-character-controller

This was verified simply by printing a string at the start of Update and FixedUpdate for the moving platform; when framestepping, I could see that the FixedUpdate string was printed once, followed by the Update string. I know it’s not guaranteed though, in case the frame rate dips.

Wait - this is it. Thank you!
If I change Interpolate to None in the moving platform’s Rigidbody2D, the two deltas are now identical.

I’m reading more about the Interpolate setting - with Interpolate turned on, I suppose it was picking a position in between last frame’s position and this frame’s position? I tried this with a debug script, and it seems that the two deltas are in sync when the body is set to Extrapolate or None.