Search Unity

Question 2D Rigidbody Interpolation changes Z?

Discussion in 'Physics' started by DanielThomas, Sep 2, 2021.

  1. DanielThomas

    DanielThomas

    Joined:
    Mar 30, 2013
    Posts:
    111
    Does the 2D rigidbody interpolation change the whole transform? As in: does it also interpolate the Z position?

    I had some issues and it seems like this is the case. I had to force set the Z position to the last frames value in the Update().

    I might be wrong, but if that's the case:
    - As the 2D rigidbody doesn't have any settings for Z, wouldn't it would make more sense if it didn't interpolate Z?
    - Where in the update loop is the interpolation done? If I would need to override it, where in the frame would be the best place to do this?

    Maybe a bit offtopic: in the case of one wanting to write a similar interpolation(to have more control over it), does rigidbody only interpolate the transform between two fixedupdates or does it do other calculations and checks?

    Thanks!
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,481
    No, it doesn't change the Z position. It also has to do a whole bunch of Quaternion dancing to ensure it doesn't change the XY rotation too, only the Z rotation. If you modify the Transform however, which you should never do if using physics, then it'll immediately stop interpolating.

    Interpolation moves the body pose from the previous simulation step pose to the current simulation step pose. It does this each frame. With interpolation, the Transform is therefore historic and behind where the body pose actually is.

    You don't "override" interpolation. If you don't want it, turn it off for that Rigidbody2D.
     
  3. DanielThomas

    DanielThomas

    Joined:
    Mar 30, 2013
    Posts:
    111
    Thank you for the reply!
    I'm probably misunderstanding, but something is moving the Z between frames.

    I've attached a super simple scene (using 2021.2). You can run and see the debug messages, but if you set Rigidbody interpolation to none the debug messages stop. Strangely enough, if you turn interpolation back on again it doesn't start sending debug messages.

    I'm aware one shouldn't mess directly with the transform when using physics, but I was thinking it would be safe if I "only" change the Z as it's not used for 2D physics. If that messes with 2D physics, is there another way (except using 3D physics)?
     

    Attached Files:

  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,481
    Essentially you're making this really hard for yourself. Adding a Rigidbody2D means it's in charge of the Transform, full stop. Using interpolation obviously also means it's driving it per-frame too. There is no way to "just change Z". You are updating the position and irrelevant of the intention to modify only the Z component, you're changing the Vector3 so it's flagged as changed.

    If you have visuals that need to be modified in Z then simply place them on another GameObject as a child. You could also make a relative change in Z here too by using local Z position. You are free to do whatever you like with this; just don't place physics components on that GameObject.

    Also, be careful when comparing floats too. A more appropriate check would be:
    Code (CSharp):
    1. if (!Mathf.Approximately(_previousZ, transform.position.z))
     
  5. DanielThomas

    DanielThomas

    Joined:
    Mar 30, 2013
    Posts:
    111
    Got you. I do understand that it's a new vector, I'm not sure I understand what the implication of changing the Z is for the 2D physics (since x,y are copied), why does it care if the vector was changed if its intention is to have full control, meaning it would assume nothing else changes it? Is it an internal check as a fail safe in case something external changes it?

    My naive understanding was that you don't want to mess with the transform because the rigidbody can move through something while there is no physics checks and it won't know where it has been in the next fixed update (hence why I thought changing Z would be fine as it's not in the 2D physics calculation).

    Sorry for harping on about Z, but I'm trying to understand if it will actually give problems for Physics calculations and I need to rehaul my whole aproach or if it's just a bit hacky.

    Actually missed that there was an Approximately(), that will clean up my 'float-float smaller than' comparisons. Thanks!
     
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,481
    Nothing you're doing is affecting physics calculations, your script doesn't check if it's affecting physics. Your script doesn't like the fact that Z isn't staying in the test as you expect because you have interpolation on where it's interpolating from/to a position.

    Honestly, this is one of those times where you should stick to the rules; don't change the Transform on a GameObject with a physics component (yes I'm repeating it). I've given you the correct way to do this which is change the Transform on any other GameObject. In your project, do that on a child and it works perfectly fine. I did this on your project and it works fine. Stick your renderer on that (or whatever).

    Why would you want to change the Z on GameObject designed for 2D physics? As I've said but you've not confirmed, this can only be for some 3D reason such as rendering so do that on the child. I have no idea why this is a "rehaul my whole approach" thing.
     
  7. DanielThomas

    DanielThomas

    Joined:
    Mar 30, 2013
    Posts:
    111
    Yes, that was the point of the test, which was my initial question in the original post. So it does, in fact, interpolate/change Z. The actual package I attached has nothing to do what my project, it was done in 5min to show the problem from my initial question.

    Yes, I totally get how the approach can be done, but I wanted to make sure that my current solution is an actual problem before the overhaul. It's a 2.5D top down project with verticallity. The visuals are sprites slanted up to the camera to allow for shadow casting and other nice stuff that depth allows for. The reason this is a "rehaul thing" is that, from what I imagine at the moment, the rigidbody need to keep adjusting it's velocity to keep up with characters moving up slopes etc, or it would be much lower than the actual visuals and collision, hit boxes etc.

    As mentioned in initial post, everything is actually working, but I was threwn off by the fact the 2D physics interpolation made the transforms Z change. In the end I might just switch over to 3D physics as it could make sense from a world movement perspective.

    Thanks again!
     

    Attached Files:

    • 25D.gif
      25D.gif
      File size:
      3.5 MB
      Views:
      269
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,481
    It's very common to split physics and visuals into different GameObjects but if you feel this somehow means you have to use 3D physics then so be it.

    Note that it isn't doing an arbitrary "change" to Z. It HAS to write Vector3 and it has already read and established what it'll write to Z prior to your script change (it reads from the Transform) and it's done immediately after. You're interrupting this process which is why we cannot state enough, don't modify the Transform on such as GameObject! Separate out your GameObjects appropriately which should be a trivial thing to do.

    To be clear; I took your example project, adding a child, moved the script to the child and it worked without issue.
     
  9. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,481
    Another thought for you; have you considering setting physics to run per-frame with a variable time-step? Lots of games are perfectly suited to this then things like interpolation go away because everything is in-sync. You can change that in the 2D physics settings.