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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Physics bodies in different location from transforms

Discussion in 'Physics' started by Dj_Payload, Jan 18, 2018.

  1. Dj_Payload

    Dj_Payload

    Joined:
    Mar 16, 2017
    Posts:
    5
    Hi all,

    We're currently on Unity version 2017.1.03f and have been looking to upgrade to version 2017.2.x or later for a while now, but several physics issues are preventing us from doing so.

    All issues revolve around the physical representation of the object not matching the actual position of the object (Transform). This can be visualised with the physics debugger and observed through gameplay by not responding to raycasts or collisions in the expected location.
    The issues were introduced in 2017.2.x and remain unresolved in later versions.

    We've managed to work around most cases by forcibly disabling and then re-enabling any enabled colliders in the affected hierarchy, but attempts to apply this work around to this latest issue have so far been unsuccessful.

    In this latest example we spawn and position an object (in a particular sequence) and after that's all done the physical body ends up offset from the visible transform. These offsets/issues persist across multiple frames, and child colliders can be added or removed from the heirarchy without resolving the issue.
    Reading out the Transform.position and Rigidbody.position in the Update loop reflects this difference in position.

    physics_offset_1.png

    We've been working on abstracting out a simple to use repro case to send in, but unfortunately this has yet to reproduce outside our project.

    Has anyone had a similar experience where the Transform and Rigidbody positions are out of sync over multiple frames? And did you find any alternative ways to fix the issue?


    Attached are a few images illustrating the issue. Taken with Physics debugger enabled, default settings:
    1. (image above) Note the physical representation (purple) is offset from the transforms (yellow blocks). The loose block to the right is sitting on the ground, physics matching transform as expected.
    2. (physics_offset_2) The loose block can be positioned intersecting with the kinematic stack of yellow blocks (mesh only) without any phsyical consequences.
    3. (physics_offset_3)The block is now parented under the kinematic stack, with the collider being added to the physical representation. The incorrect offset on the root object is maintained.


    4. (image below) A slightly different example where re-parenting a child collider to a different object moved the transform over to the new parent, yet the collider remained under the original parent.
      Note the single empty collider shape (middle top) that does not seem to match any mesh. The mesh it is supposed to match to is the single 3x1 grey block on top of the 2 kinematic towers in the bottom left. dmKRFk1qur54kZacwqjQXA.png
     

    Attached Files:

  2. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Do you have non kinematic rigidbodies anywhere here? What you describe sounds very much like you have a non kinematic rigidbody as a child in the mix somewhere.
     
  3. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Also, the transform and rigidbody could very well be different in Update and validly so depending on how exactly you are moving them. Like if you are just moving the transform via position, I would expect the rigidbody to then not be in sync for some time.

    Now if there is a bug here, and assuming you are moving transforms via position, I bet it would go away by using rigidbody.MovePosition. Because transforms are technically supposed to follow the rigidbody, not the other way around. I wouldn't expect it to be like in the pictures, where it just sticks, but I could see it being off like that for short time periods, like between the Update where you change the position and the next FixedUpdate.
     
  4. Dj_Payload

    Dj_Payload

    Joined:
    Mar 16, 2017
    Posts:
    5
    Thanks for your reply snacktime.

    We don't.
    That said the code in its current form does removes the rigidbody from the individual blocks after they are parented (but in the same update frame). The parent is non-kinematic at that time and is changed to kinematic after all children have been added.
    To rule that out I've tested removing the rigidbody before any parenting occurs, using both Destroy and DestroyImmediate. Neither action does anything to change the outcome of the test - physics are still offset.


    That's exactly the maximum time frame I would expect the transform and rigidbody to be out of sync. After the FixedUpdate the internal Physics update should be taking care of syncing the rigidbody to the transform and vice versa.
    As you can see in the example above the desync persists much longer than that, and in fact does not resolve itself at all.

    While using rbody.MovePosition isn't really realistic for those cases within our project, and using it really shouldn't be necessary when positioning an object in the same frame it is instantiated - I ran it as a test just out of interest.
    Funnily enough, it actually seems to make the problem worse:

    Result replacing transform.position with rbody.MovePosition in the final move operation after spawning the objects and parenting all children.

    Note the initial offset already present between transform and rbody before moving.
    Code (CSharp):
    1. rbody position was        (3.7, -0.8, -14.9)
    2. transform position was (3.3, -2.3, -15.5)
    3.  
    4. rbody position now        (3.3, -18.2, -15.5)
    5. transform position now (3.3, -2.3, -15.5)
    (no Internal Physics Update to sync it yet, hence the offset after the move)

    Setting rbody to kinematic (same Update frame)
    Code (CSharp):
    1. trans position        (3.3, -2.3, -15.5)
    2. rbody position       (3.3, -18.2, -15.5)
    (unchanged from before - still in the same Update call and no Internal Physics Update has happened)

    After that, the Transform never syncs to the rbody at all, leaving an offset of ~16 units on the vertical axis.

    Any position update after the initial spawn frame - transform.position, rigidbody.position and rigidbody.MovePosition - aswell as changing the body to non-kinematic seem to flag the object as dirty and in need of syncing. The next InternalPhysicsUpdate will then sync both transform and rigidbody correctly.
    Unfortunately, doing a position update in the same frame (after changing to kinematic) does not have the same effect.

    Note that manually forcing the positions to be the same at the end of the spawning process, eg
    Code (CSharp):
    1. // Force sync transform and rigidbody to the same position
    2. Vector3 expectedPosition = trans.position;
    3. trans.position = expectedPosition;
    4. rbody.position = expectedPosition;
    does not prevent the issue from occurring.
     
    Last edited: Jan 19, 2018
  5. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    Go to the Physics Manager in Edit->Project Settings->Physics and make sure "Auto sync transforms" is enabled. You can also set this in code with Physics.autoSyncTransforms = true;
     
  6. Dj_Payload

    Dj_Payload

    Joined:
    Mar 16, 2017
    Posts:
    5
    Thanks, this is enabled. Transforms and rigidbodies sync as expected in the vast majority of our game.

    This worked fine in Unity 2017.1.03f and has only become broken in version 2017.2 and up, including the 2018.1 Beta.
     
  7. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    I'm wondering if changing the hierarchy like you are is causing this. I would count that as a bug but it just seems like the type of edge case that might mess with the auto sync transform logic which is new in 2017.

    Another thing to try is turn off auto sync and sync manually.
     
  8. Dj_Payload

    Dj_Payload

    Joined:
    Mar 16, 2017
    Posts:
    5
    It's bound to be some combination of turning an object kinematic, adding children, potentially removing components and updating the transform position - possibly more than once - in some order in the same frame.
    The question is what is that combination, and more importantly how to get around it.

    Unfortunately turning off autosync at this stage in the project is likely to create more problems than that it'll fix.
    As a test we've tried forcing a sync through various ways, but there doesn't seem to be any exposed way to do this. (@Unity - ForceSync(Transform) or ForceSync(Rigidbody) would be great in this scenario).