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. Dismiss Notice

Rigidbody2D.position doesn't teleport the object with the interpolation settings on

Discussion in 'Physics' started by Develax, Sep 20, 2021.

  1. Develax

    Develax

    Joined:
    Nov 14, 2017
    Posts:
    67
    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):
    1. Is the differences in the descriptions mutually applicable (to both types of rigidbodies)?
    2. Why does
      Rigidbody2D.position
      interpolate the object after the first
      FixedUpdate
      while it shouldn't?
    3. What is the correct way to teleport the kinematic
      Rigidbody2D
      with the interpolation settings "on"?
    ----------------------
    Unity 2021.1.17f
     
    Last edited: Sep 20, 2021
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    1. 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.
    2. 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.
    3. 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?
     
  3. Develax

    Develax

    Joined:
    Nov 14, 2017
    Posts:
    67
    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.
     
    Last edited: Sep 21, 2021
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    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.
     
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    Send me your test project and I'll have a look.
     
  6. Develax

    Develax

    Joined:
    Nov 14, 2017
    Posts:
    67
    The problem is that it does not stop interpolation. I would be happy if it did :)

    > Send me your test project and I'll have a look.
    Ok, I'll put the link to the project today.
     
  7. Develax

    Develax

    Joined:
    Nov 14, 2017
    Posts:
    67
    In this project (link):
    - 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:
     
    MelvMay likes this.
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    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:
    https://gyazo.com/630e7049e8672ea0337e3a67c80b1542

    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!
     
  9. Develax

    Develax

    Joined:
    Nov 14, 2017
    Posts:
    67
    Thank you for the details and quick fix!

    Here is the bug report (Case 1367721) : https://fogbugz.unity3d.com/default.asp?1367721_l3ao7dkdn0r45v6c


    It is said here that
    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:

    Code (CSharp):
    1. Rigidbody2D rb = tr.GetComponent<Rigidbody2D>();
    2. var tr = transform;
    1. Changing Rigidbody2D.position along with Transform.position and turning the object off&on:
    Code (CSharp):
    1. tr.gameObject.SetActive(false);
    2. rb.position += (Vector2)shift;
    3. tr.position += shift;
    4. tr.gameObject.SetActive(true);
    2. Turning interpolation off & on when changing rigidbody position:
    Code (CSharp):
    1. tr.gameObject.SetActive(false);
    2. rb.position += (Vector2)shift;
    3. tr.position += shift;
    4. tr.gameObject.SetActive(true);


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

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    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):
    Code (CSharp):
    1. _rb.interpolation = RigidbodyInterpolation2D.None;
    2. _rb.position += Vector2.right; // this doesn't stop visual interpolation
    3. _rb.interpolation = RigidbodyInterpolation2D.Interpolate;
    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.
     
  11. Develax

    Develax

    Joined:
    Nov 14, 2017
    Posts:
    67
    I can create a demo project to demonstrate this "freezing" if you would be interested in looking into it.
     
  12. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    Hi! I just updated my post above with more info for your workaround!
     
  13. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    I'd say update the (Github) project above and I can look at it there.
     
  14. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    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! :)
     
  15. Develax

    Develax

    Joined:
    Nov 14, 2017
    Posts:
    67
    Yes, that's exactly how I read it and was almost ready to give up.

    Okay, I'll add another scene to it and let you know when it's ready.
     
  16. Develax

    Develax

    Joined:
    Nov 14, 2017
    Posts:
    67
    This is exactly what I was going to write and even wrote the correct subtitle,
    upload_2021-9-23_11-29-33.png
    but then just duplicated the code from the previous example.

    The code I intended to write was this:

    Code (CSharp):
    1. Rigidbody2D rb = player.GetComponent<Rigidbody2D>();
    2. RigidbodyInterpolation2D interpolation = rb.interpolation;
    3. rb.interpolation = RigidbodyInterpolation2D.None;
    4. rb.position += (Vector2)shift;
    5. rb.interpolation = interpolation;
     
    MelvMay likes this.
  17. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    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.
     
  18. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
  19. Develax

    Develax

    Joined:
    Nov 14, 2017
    Posts:
    67
    I received it by email after submitting the bug report from Unity editor
    upload_2021-9-23_15-29-57.png
     
    MelvMay likes this.
  20. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    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.

    Anyway, the public link is now available too.
     
  21. Develax

    Develax

    Joined:
    Nov 14, 2017
    Posts:
    67
    Here is my new demo (the last commit in the same project).
    The scene name is "FreezeTest".
    It contains 3 "Ground" objects, following closely after each other (just 3 clones).

    upload_2021-9-23_22-4-14.png

    Each "Ground" object contains simple objects (like black pole and green tree) so that the player's (white circle) movement is noticeable. When the player reaches the end of the 2-nd Ground object (marked by black pole) it is teleported to the end of the 1-st Ground, this creates the illusion of an infinite runner. Since teleportation occurs when the player is in the process of moving, it must be smooth so that the movement looks natural, as if there were no teleportation at all.

    The Player object has 3 components on it: PlayerMove1, PlayerMove2, and PlayerMove3.
    All of them are inherited from the PlayerMoveBase abstract class and override only one method: teleport.
    Each overridden method uses a different workaround for teleportation. The scripts move the Player object when pressing keys 1, 2 and 3, respectively.

    For this particular demo, only the worst (most expensive) workaround (PlayerMove3) gives a nice movement+teleportation experience:

    Code (CSharp):
    1. public class PlayerMove3 : PlayerMoveBase
    2. {
    3.     protected override void teleport(Vector2 pos)
    4.     {
    5.         gameObject.SetActive(false);
    6.         _rigidbody.position = pos;
    7.         transform.position = pos;
    8.         gameObject.SetActive(true);
    9.     }
    10. }
    2 others cause "freezing" and "interpolation" side effects which are well noticeable even at normal speed.
     
    Last edited: Sep 24, 2021
  22. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    I took at look at this but even though you provided a lot of detail, you don't really point out what I'm supposed to be looking for. Maybe because it's super clear on your machine and it's not here but so I have no idea what this "freezing" looks like even though you state it's noticable.

    Just wanted to point out in-case it's a source of confusion but changing the Transform position doesn't change anything when the call returns apart from the Transform. There's no notifications that this has changed to any other part of Unity including the 2D/3D physics systems. The body will be updated when the simulation step runs because its first task is to check if Transforms have been manually changed. The Transform system provides this as a feature because it's the only way to know it was changed. This is PlayerMove1 which you state as "freezing". The same with changing the body, it doesn't change the Transform until the simulations step occurs.

    Maybe you're just seeing some artifact that relates to the previous fix or it's the disconnect between per-frame and when the simulation runs but I don't understand the freezing so I cannot test that. Have you tried running the physics per-frame as a test; you can change that in the 2D Physics Settings (Simulation Mode).

    FYI: The fix above and backports have been processed and are with QA which is now shown in the public link here. Also note that this issue affected rotation too (both setting rotation by angle or via Quaternion) so that too has been fixed.
     
  23. Develax

    Develax

    Joined:
    Nov 14, 2017
    Posts:
    67
    Sorry, I didn't get this, are these fixes already available in any of the Unity versions? It looks they are in a review state now.

    This was clearly noticeable on my laptop, so I didn't record a video.
    Teleportation occurs as soon as the object goes behind the black pillar, and this is exactly where the object stops for a second when using
    transform.position = pos;
    for teleportation. The expected movement, however, should be smooth.
    upload_2021-9-27_23-38-49.png



    I don't quite understand what you mean. I will quote parts I'm confused with:
    > the Transform position doesn't change anything when the call returns apart from the Transform
    What does it mean: call returns apart from the Transform?
    > The body will be updated when the simulation step runs because its first task is to check if Transforms have been manually changed.
    Do you mean "rigidbody"? If Transforms have been manually changed the physics system will calculate the next rigidbody position based on the changed
    Trasfrom.position
    , and not on the
    Rigidbody2D.postion
    ?

    I haven't tried it yet. I will check it tomorrow.
     
  24. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    No, the fixes have been pushed and QA are reviewing them now (In Review State) then when they pass that they'll get added to the release stream(s) queue and eventually land. They'll then go out in the next release.

    Performing "transform.position =" changes the Transform position only. Might seem obvious but to be clear, this doesn't modifying anything else upon the completion of that call. There's no notifications internally to Unity to tell things like the physics systems that a change has happened. The physics system only knows next time the simulation steps, at which point it sees the change and updates the body.

    I'm not talking about interpolation. Just saying what I said above.

    Honestly, pretty simple. Changing the Transform ONLY changes the Transform until the physics simulation steps. That's it.
     
  25. Develax

    Develax

    Joined:
    Nov 14, 2017
    Posts:
    67
    I have tried setting Simulation Mode = Update and this caused constant intermittent movement (not only when teleportation occurs but every frame). I guess it's because interpolation doesn't work in this mode.

    Could you, please, check one more time if you don't really notice any stops of the white circle as in the last video (just after the black poles) when holding key "1" ? I checked this project on another computer and it showed the same: the object stops for a moment after the black poles.
    Time Scale should be 0.05 in the Project Settings.
     
    Last edited: Sep 29, 2021
  26. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    I don't follow this at all. How can there be any issue with this, everything is running in-sync with the frame-rate. Have you tried just setting the Transform without a physics object?

    I've been pressing it and releasing it for each move. Wasn't aware I needed to hold it down continually. I'll try that.

    EDIT: I hold down that key and I see it so looking at your code you're poking at moving from too opposing things AND wanting interpolation but wanting Unity to figure it out the conflict. The physics system wants to control movement so you have to use that. Right now you're issuing MovePosition calls which will happen during the next physics simulation step AND you're changing the Transform AND you've got interpolation on. It cannot know which one has priority for you but also your code modifies the Transform and as I've said above, the Rigidbody2D isn't updated when you do that until the simulation step but you're also asking it to MovePosition based upon its current position.

    I turned off simulation (property on the Rigidbody2D) so it's essentially off. I then changed:
    Code (CSharp):
    1.     private void moveForward()
    2.     {
    3.         //_rigidbody.MovePosition(_rigidbody.position + _velocity);
    4.         transform.position += (Vector3)_velocity;
    5.     }
    6.  
    This means it's all Transform changes. Alternately I changed it so that the root position it should ".MovePosition()" from is either the Transform.position (if a "teleport" happens i.e. you changing it) or the Rigidbody2D.position (if a "teleport" doesn't happen).

    Code (CSharp):
    1.     private void FixedUpdate()
    2.     {
    3.         if (!_move)
    4.             return;
    5.  
    6.         _move = false;
    7.  
    8.         var hasTeleported = checkTeleportTrigger();
    9.         moveForward(hasTeleported ? transform.position : _rigidbody.position);
    10.     }
    11.  
    12.     private bool checkTeleportTrigger()
    13.     {
    14.         if (_rigidbody.position.x < _teleportTriggerX)
    15.             return false;
    16.  
    17.         Debug.Log($"Teleport: {this.GetType().Name}");
    18.         teleport(new Vector2(_rigidbody.position.x - _groundSize.x, _rigidbody.position.y));
    19.         return true;
    20.     }
    21.  
    22.     private void moveForward(Vector2 rootPosition)
    23.     {
    24.         _rigidbody.MovePosition(rootPosition + _velocity);
    25.     }
    26.  
     
  27. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    Thought I'd add this because, honestly, the above is making things really complicated for something so simple. If you run the physics per-frame then you don't ever need interpolation and Unity will never use it, even if you ask for it. This means you continue to use MovePosition exclusively. Don't ever modify the Transform as this is the conflict.

    Set it to per-frame simulation steps and try this code which works perfectly and no silly Transform updates required. As you can see, it performs your usual "moveForward" else if you teleport, it moves to the teleport position instead. Also note that in this example, it's all in Update because the physics runs synchronously to this.
    Code (CSharp):
    1.  
    2. private void Update()
    3. {
    4.     if (!Input.GetKey(_moveKey))
    5.         return;
    6.    
    7.     if (_rigidbody.position.x < _teleportTriggerX)
    8.     {
    9.         _rigidbody.MovePosition(_rigidbody.position + _velocity * Time.unscaledDeltaTime);
    10.         return;
    11.     }
    12.  
    13.     Debug.Log($"Teleport: {this.GetType().Name}");
    14.     _rigidbody.MovePosition(new Vector2(_rigidbody.position.x - _groundSize.x, _rigidbody.position.y));
    15. }
    16.  
    NOTE: _ used unscaledDeltaTime here because of your time-scaling but normally you would just use "deltaTime"
     
  28. Develax

    Develax

    Joined:
    Nov 14, 2017
    Posts:
    67
    I think it is because the TimeScale is set to 0.05 for testing interpolation in FixedUpdate mode. In Update mode it may cause the opposite effect.
     
    Last edited: Sep 29, 2021
  29. Develax

    Develax

    Joined:
    Nov 14, 2017
    Posts:
    67
    It looks Ok. I can change it later to using Rigidbody when your fix is released.

    Can physics calculations in this mode lead to any other issues or side effects? I mean is it absolutely safe to use Update instead of FixedUpdate for physics?
     
    Last edited: Sep 29, 2021
  30. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    If by "safe" you mean will it work then yes. If you're doing something like adding a force of a constant value then it'll not be frame-rate independent, it'll increase as the frame-rate does but so would doing so in fixed-update but it'd be fixed-update rate dependent so increasing the rate there would change the force.

    This is why when adding forces or acceleration (as in your code) you scale by the elapsed time so you're not adding a constant, you're adding it scaled by the elapsed time so it's constant over time.

    Setting the time-scale to 1 I used this and it's smooth without issue:
    Code (CSharp):
    1.     private void Update()
    2.     {
    3.         if (!Input.GetKey(_moveKey))
    4.             return;
    5.        
    6.         if (_rigidbody.position.x < _teleportTriggerX)
    7.         {
    8.             _rigidbody.MovePosition(_rigidbody.position + (_velocity * Time.deltaTime));
    9.             return;
    10.         }
    11.  
    12.         Debug.Log($"Teleport: {this.GetType().Name}");
    13.         _rigidbody.MovePosition(new Vector2(_rigidbody.position.x - _groundSize.x, _rigidbody.position.y));
    14.     }
     
    Develax likes this.
  31. Develax

    Develax

    Joined:
    Nov 14, 2017
    Posts:
    67
    Yes, no issues are noticeable to the eye, although I think this is a bit incorrect logically: it should make a move even when teleportation occurs (in the same update). IOW teleportation is a trick to visualize endless running in a limited range of X coordinates. At the same time, the object is constantly moving regardless of whether the trick was performed or not. So I think this example would be logically more correct:

    Code (CSharp):
    1. private void Update()
    2. {
    3.     if (!Input.GetKey(_moveKey))
    4.         return;
    5.  
    6.     if (_rigidbody.position.x > _teleportTriggerX) // teleportation can happen or not...
    7.         _rigidbody.position = new Vector2(_rigidbody.position.x - _groundSize.x, _rigidbody.position.y);
    8.  
    9.     // .. but the object makes a move every step
    10.     _rigidbody.MovePosition(_rigidbody.position + (_velocity * Time.deltaTime));
    11. }
     
  32. Develax

    Develax

    Joined:
    Nov 14, 2017
    Posts:
    67
    I could go with the previous working example and wouldn't bother you with this, but, well, this example doesn't help with "stopping" when teleporting. This is interesting to me, so I looked into it a little. What happens here is that just after the
    transform.position
    is changed in the
    teleport()
    method the
    _rigidbody.MovePosition()
    doesn't do anything up to the next FixedUpdate. IOW
    transform.position
    is not being changed up to the next FixedUpdate as it normally is if no teleportation (changing
    transform.position
    ) occurs. The log proves it:


    Update: transform.position.x = 14.89941, _rigidbody.position.x = 14.946
    Update: transform.position.x = 14.89941, _rigidbody.position.x = 14.946
    FixedUpdate: transform.position.x = 14.89941, _rigidbody.position.x = 14.946
    // after this
    transform.position.x is being interpolated up to the next FixedUpdate:
    MovePosition(15.446)
    Update: transform.position.x = 14.96772, _rigidbody.position.x = 15.446
    Update: transform.position.x = 14.96772, _rigidbody.position.x = 15.446
    Update: transform.position.x = 14.96772, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.03236, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.03236, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.03236, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.08148, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.08148, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.08148, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.15591, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.15591, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.15591, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.21049, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.21049, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.21049, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.28232, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.28232, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.28232, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.35494, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.35494, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.35494, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.42184, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.42184, _rigidbody.position.x = 15.446
    Update: transform.position.x = 15.42184, _rigidbody.position.x = 15.446
    FixedUpdate: transform.position.x = 15.42184, _rigidbody.position.x = 15.446
    Teleport!
    // after this
    transform.position.x is NOT being interpolated up to the next FixedUpdate (because of the Teleport call before it):
    MovePosition(5.921839)
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    Update: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    FixedUpdate: transform.position.x = 5.421839, _rigidbody.position.x = 5.421839
    // and here it starts working again (since not teleportation occurs):
    MovePosition(5.921839)
    Update: transform.position.x = 5.424759, _rigidbody.position.x = 5.921839
    Update: transform.position.x = 5.424759, _rigidbody.position.x = 5.921839
    Update: transform.position.x = 5.424759, _rigidbody.position.x = 5.921839
    Update: transform.position.x = 5.478089, _rigidbody.position.x = 5.921839
    Update: transform.position.x = 5.478089, _rigidbody.position.x = 5.921839
    Update: transform.position.x = 5.478089, _rigidbody.position.x = 5.921839
    Update: transform.position.x = 5.536054, _rigidbody.position.x = 5.921839
    Update: transform.position.x = 5.536054, _rigidbody.position.x = 5.921839
    Update: transform.position.x = 5.536054, _rigidbody.position.x = 5.921839
    Update: transform.position.x = 5.603037, _rigidbody.position.x = 5.921839
    Update: transform.position.x = 5.603037, _rigidbody.position.x = 5.921839
    Update: transform.position.x = 5.603037, _rigidbody.position.x = 5.921839
    Update: transform.position.x = 5.65183, _rigidbody.position.x = 5.921839
    Update: transform.position.x = 5.65183, _rigidbody.position.x = 5.921839
    Update: transform.position.x = 5.65183, _rigidbody.position.x = 5.921839
    Update: transform.position.x = 5.702931, _rigidbody.position.x = 5.921839


    My try to depict this for clarity:
    upload_2021-9-29_23-52-3.png


    Also I tried to replace
    _rigidbody.position
    with
    transform.position
    since we are then changing
    transform.position
    in the teleportation method, but this didn't help.

    Code (CSharp):
    1. private bool tryTeleport()
    2. {
    3.     if (transform.position.x < _teleportTriggerX)
    4.         return false;
    5.  
    6.     teleport(new Vector2(transform.position.x - _groundSize.x, transform.position.y));
    7.     return true;
    8. }
    Maybe this is related to the fixes you've made.