The description of Rigidbody2D.MovePosition seems to be more detailed but then the question arises: whether the differences in the descriptions mutually applicable (to both types of rigidbodies)?
For example, the Rigidbody.MovePosition description sounds like it moves only a kinematic rigidbody. It also explicitly states that MovePosition complies with the interpolation settings and position should be used for teleportation needs.Unfortunately, the last statement does not correspond to reality, at least this is not the case for Rigidbody2D. My experiments have shown that both: Rigidbody2D.MovePosition and Rigidbody2D.position comply with interpolation settings.
The first part of the video demonstrates the movement of two Rigidbody2D kinematic objects via MovePosition & position with the interpolation “on”. Then I turn off interpolation and play the same scene. Time is set to 0.01, so you can easily observe that interpolation works in the first part and does not in the second. Also in the first part you can notice that changing Rigidbody2D.position with interpolation settings “on” really teleports the object (as documentation claims) but only in the first FixedUpdate, then it is interpolated along with Rigidbody2D.MovePosition.
So, my questions are (the most important one is the 3rd):
Is the differences in the descriptions mutually applicable (to both types of rigidbodies)?
Why does Rigidbody2D.position interpolate the object after the first FixedUpdate while it shouldn’t?
What is the correct way to teleport the kinematic Rigidbody2D with the interpolation settings “on”?
2D and 3D are completely different implementations and I’m not going to get into any differences because they are not always the same due to the inherent different engines behind them. I can only speak for 2D.
Rigidbody2D MovePosition can be used on both a Kinematic and Dynamic body. Unlike 3D it also works correctly for any manual simulation and for Dynamic it covers the distance inbetween (not just an instant pose change). In both cases, that feature calculates a temporary velocity to move the body during the next simulation step. This is compatible with interpolation because it’s normal movement. I will add that for 3D, it only works for Kinematic bodies.
If you modify either the Transform or the Rigidbody2D pose, it’ll stop interpolation until the next simulation step. The body will be at that pose until then. Interpolation is the act of moving it from an old position to the current position per-frame until the next simulation step. If you try to alter that while using it, it has no option but to temporarily stop using interpolation until it can be set-up during the next simulation step. If you were to set the position 1000m away, we don’t want it interpolating from the old position to this new position. In short, you don’t “teleport”. You use MovePosition to move Kinematic bodies.
So we’re clear here because what you’re asking seems to be contradictory. By teleport you’re indicating instantly changing position (let’s make this 10m). It’ll do that instantly you ask for it. But then you seem to want “interpolation” but interpolation ONLY affects the Transform i.e. it’s a visual thing only and nothing to do with physics so you’re asking for the body to instantly be positioned but the transform to show movement through that space? This is the contradiction I sense but it’s only a sense and I’m probably wrong on your intention so forgive me if that’s so. In the end, use MovePosition because it does that so the question would become one of, why not use it?
Perhaps I didn’t formulate the question clearly.
I’m moving a kinematic Rigidbody2D with interpolation “on” via MovePosition in FixedUpdate and I have no problems with this at all.
Then at some event, I need to teleport the object to some position without the visual interpolation effect. I expected that changing Rigidbody2D.position should do the trick, but it moves the object the same way as MovePosition does, i.e. using visual interpolation.
The main question is what is the recommended way to teleport the object without visual interpolation? Since using Rigidbody2D.position doesn’t help, are there any other options?
The Rigidbody documentation contains some recommendations for teleportation (to use Rigidbody.position), but the Rigidbody2D documentation does not. So, I expected that it could be the same that’s why I tried Rigidbody2D.position (which didn’t work). > If you modify either the Transform or the Rigidbody2D pose, it’ll stop interpolation until the next simulation step.
My experiments (in the video) show that Rigidbody2D.position doesn’t stop interpolation.
I’m not an English speaker, so if it’s not clear this time I’ll try again with some code.
It doesn’t/shouldn’t though. As I said, changing the Transform or the Rigidbody2D position/rotation stops interpolation and instantly repositions the body at that position.
If the body has velocity, it’ll continue interpolation but from that new position starting from the next simulation step. By default the simulation step is after the script FixedUpdate callbacks.
Press 1 to move the object using Rigidbody2D.MovePosition
Press 2 to move the object using Rigidbody2D.position
Time is set to 0.05, so you can observe visual interpolation.
You can see that interpolation is not stopped when pressing 2 for using Rigidbody2D.position Video demo: https://www.youtube.com/watch?v=7SsrTDbFyt4
So I’ve confirmed this incorrect behaviour and fixed it. Looking back it turns out this was a bad merge that removed an important line which resets the current/next body position although it does indeed turn-off interpolation but let me explain that because it sounds like a contradiction. If you were to issue this during a frame update, interpolation would stop however because you issue it immediately prior to a simulation step, interpolation is set-up again and runs from the previous position to the new position. At this point, the previous/current should be identical but the previous is incorrect because of the missing line mentioned above.
There’s unit tests for the behaviour of changing body position/rotation and even one to confirm interpolation is off but unfortunately it didn’t check if the interpolation previous state was reset which it now does.
Whilst I’ve fixed this already, it would help both your and I if you could officially submit this as a bug-report and pass me the case number so I can push it against it. It’ll allow you to track it landing, including its backports.
As a workaround, you can change the Transform.position which also should instantly teleport. I verified that this was the case using your test project too.
Here’s it working:
Thank you very much for not only spotting this but putting together such a clean, well presented test-case! It seems to have been like it for some time so well spotted!
Also, my experiments have shown that using Transform.position causes the object to freeze for a moment that almost imperceptible at normal speed but noticeable when Time = 0.05f or less.
So, I tried to avoid using Transform.position and came up with these 2 workarounds that worked smoothly:
Rigidbody2D rb = tr.GetComponent<Rigidbody2D>();
var tr = transform;
1. Changing Rigidbody2D.position along with Transform.position and turning the object off&on:
I would also like to ask you to supplement the Rigidbody2D.MovePosition & Rigidbody2D.position sections with the missing information (especially the latter, since it’s almost empty).
Changing the Transform does nothing to the body. When the simulation runs, Transforms are checked to see if they’ve changed and if so, the Rigidbody2D is updated to that position. We also check during the frame-update and react accordingly.
There would be no reason for a “freeze” and I don’t see that nor would I expect it in your project when I try it. It also is a workaround, I wasn’t suggesting you should ever changing the Transform moving forward. In-fact, if you go look at my posts, it’s one of the most common things I state you should never do.
Your workarounds above are really expensive as they remove all the physics objects from any physics components when you deactivate along with all the work on other components.
Logically following what you’re doing which is having interpolation on but then for a single position change, not wanting it, it would be far better to follow that logic by simply doing (from your test project itself):
As long as you are fully aware that changing the body position does not change the Transform position until there’s a simulation step and without interpolation, the same the other way around as the two are decoupled. Same with 3D physics and TBH everything else because a Transform change has no side-effects and doesn’t notify anything else in Unity.
btw, when I say “shouldn’t”, I only mean to inform you that the behaviour isn’t intended and is unexpected. When I read my replies it sounds like I’m saying you are wrong, have a vivid imagination or “doesn’t”. Not the case!
Ah! Yes, I actually looked at the code briefly and not the title so I did the opposite! So yes, that’ll be a workaround for now until I can get you the fix.
The public link is here but that isn’t active yet because it’s only just been converted to a bug so takes a little time for our infrastructure to create it.
Yes, I just asked about this internally. I wasn’t aware that you were sent that link but instead thought you needed to wait for the public link after it’d be accepted.