Search Unity

  1. Unity 2019.1 is now released.
    Dismiss Notice

[SOLVED] Since 2018.2, my child colider doesn't obey parent's local transform

Discussion in 'Physics' started by brainwipe, Jul 23, 2018.

  1. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    15
    Something has broken since updating to 2018.2: a child collider seems to lose its local position and be transformed in global space.

    In the video below, you see the scene view, when I click the building, it lights up and the collider starts moving away from the building (because it's now in scene space).



    Before I updated to 2018.2, this worked. I have not changed the code (below) since the update. Here it is working before the update:



    I have a non-kinematic rigidbody that has forces acted upon it. It has a few children that control the placing and clicking of buildings and then each building has a child collider with a rigidbody. So the structure is:

    • Main Cloudship Object [RigidBody]
      • Building Surface that controls object placement [No rigidbody]
        • Building [No rigidbody]
          • Box Collider [Collider and Rigidbody set isKinematic = true]
          • (There is another kinematic collider but we don't care about that here)

    The Rigibody is required on the Box Collider because I need the Box Collider to raise trigger events (the Collider is set to Is Trigger = true) for overlapping other buildings. I've read that you shouldn't have rigidbodies as children of other rigidbodies without a hinge but in this case, it's only kinematic for the raising of events. I don't ever change the transform of the Box Collider, only that of the parent building.

    When I click-and-hold a building, the following code sets the transform to the place under the cursor:

    Code (CSharp):
    1. Vector3 localPosition;
    2.         if (GetDesired(out localPosition))
    3.         {
    4.             selectedBuilding.transform.localPosition = Vector3.Lerp(
    5.                 selectedBuilding.transform.localPosition,
    6.                 localPosition,
    7.                 Time.deltaTime * 40);
    8.             selectedBuilding.IsOverCloudship = true;
    9.         }
    I know that this code is correct because the Building object (the mesh) stays in the right place (you can see the result of it in the top video, it's the red line). It's the collider children that move. The Lerp isn't important here, removing it causes the same effect.

    Was there a change in 2018.2 that I missed? A more strict constraint perhaps?

    I'm completely stumped, thanks in advance for your help!
     
    Last edited: Jul 25, 2018
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    1,451
    As far as I can tell, a Rigidbody simply modifies its GameObject's Transform based on the physics. Thus, a hierarchy of rigidbodies is pointless because each rigidbody acts in world space. A child rigidbody does not follow its parent's Transform.

    The mystery to me is how it actually worked before. I can figure out that the hierarchy positions and rotations were being applied after the rigidbody had modified its GameObject's Transform, so the children rigidbodies seemed to be following their parent.

    There's a recently added option (2017.2) in the Physics Manager, "Auto Sync Transforms", which may have something to do here:


    Perhaps you can get some result by adjusting this option in combination with the Physics.SyncTransforms() call:

     
    brainwipe likes this.
  3. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    15
    Edy, thank you for your help! I tried autoSync in all of its forms and that didn't have any effect. It was set to true in the examples above.

    It seems I have two options now:

    1. Add FixedUpdate to the empty game object that resets the local position each update.

    2. Restructure my game objects. Given that this is poor practice and that it should have never worked (which I quite agree, I have no idea why it did - I've looked back through my commits and the rigidbodys have always been there) then a new hierarchy is probably needed. I've already hit the problem that I need buildings to be independently clickable/moveable but still children of the parent. You can't trap Raycasts without a rigidbody and you can't use triggers without one of colliders having a rigidbody, I'm a bit stuck. Again.

    Which would you choose?
     
  4. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    15
    There is something else that's odd here. It does still work when I'm not updating the transform of the building (the box collider's parent). I appears to happen when updating localPosition or position (global scope).
     
  5. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    15
    Brief update on this, I created a scene that was a super-simplified version of what I had before.



    You're seeing:
    • Cream cuboid, Rigidbody, non-kinematic (no gravity), small force applied in FixedUpdate
      • White cube with script that changes local position in FixedUpdate. No rigidbody.
        • Collider layer with kinematic rigidbody, trigger set to true.
    Having a non-kinematic rigidbody root with a kinematic rigidbody child works fine. However, if you then adjust the transform of the white cube (middle layer) then the children of that rigidbody are not updated.

    I've discovered a solution to be setting the contraints of the Collider layer rigidbody to frozen position. How did this "ever work"? I don't know but this does solve my problem.
     
  6. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    15
    I'm still getting very odd behaviour that I can't explain. Is there anyone at Unity that can help?

    In the video below I'm drawing a ray from the camera to the base of the two small green colliders attached to the building. The ray is green when it detects a hit and red when it doesn't. When the building appears, the green colliders stay fixed to their parent mesh objects. As the base moves along under physics, the ray from the camera turns red. Even though the collider has stayed where it is. It looks like the ray is intersecting at first but as physics pushes the object hierarchy, whatever the ray relies upon isn't being pushed. The box collider is being pushed, because you can see it still attached to the object.



    Is the ray really intersecting with the green collider box or is that some graphical sugar? I'm completely stuck and confused. This worked in Unity 2017.x.
     
  7. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    15
    After a lot of iterations and trial and error I have it working - for now...

    What I did was to add another rigidbody to the Building. This is the thing highest point in the hierarchy that we want the mouse to click on and move. My new hierchy looks like:

    • Main Cloudship Object [RigidBody]
      • Building Surface that controls object placement [No rigidbody]
        • Building [Rigidbody, isKinematic = true]
          • Box Collider [Collider and Rigidbody set isKinematic = true]
          • (There is another kinematic collider but we don't care about that here)

    The second change I made was to replace
    transform.localposition = mouseposition
    with global positions and rotations everywhere and then using
    building.rigidBody.MovePosition(mouseposition)
    .

    MovePosition calculates the velocity and updates the position in the next frame, which seems to work in this case.

    I hope this helps others track down their own problems.