Search Unity

  1. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  2. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  3. Want more efficiency in your development work? Sign up to receive weekly tech and creative know-how from Unity experts.
    Dismiss Notice
  4. Participate with students all over the world and build projects to teach people. Join now!
    Dismiss Notice
  5. Build games and experiences that can load instantly and without install. Explore the Project Tiny Preview today!
    Dismiss Notice
  6. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  7. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Child rigidbody doesn't act normally when parent rigidbody moves

Discussion in 'Physics' started by Stranger-Games, Oct 5, 2018.

  1. Stranger-Games

    Stranger-Games

    Joined:
    May 10, 2014
    Posts:
    290
    Hi,

    I have a physical object that moves using rigidbody. It has a child with its own collider and the collider act as expected, for example if there's an object above a child collider and the parent rigidbody moves, the object lying above the collider is affected correctly.

    upload_2018-10-5_7-22-57.png
    image of parent object (the small box above is affected with parent rigidbody movement if the child doesn't have rigid body)

    upload_2018-10-5_7-10-49.png
    image of the child object with rigidbody added (the small cube above isn't affected with parent rigidbody movement after adding rigidbody to the child)

    However if I add to that child collider (like in second image) its own rigidbody and moved the parent rigidbody, the child collider acts as if non physical transform is called. For example if there's an object above the child collider with the rigidbody, it's not affected with the movement at all.

    The reason I want to add a rigidbody to that child object is because sometimes I want to move the child independent from its parent rigidbody. Which works correctly, but I want it also to work correctly when the parent rigidbody moves even if the child has its own rigidbody.

    Scenario 1: child has no rigidbody, moves with parent and affects other bodies (small box above)
    child working 2.gif

    Scenario 2: child has rigidbody, moves with parent but doesn't affect other bodies (small box above)
    child not working.gif

    Scenario 3: child has rigidbody but moves independent from parent rigidbody, affects other bodies correctly (small box above)
    child independence.gif

    Thanks for advance
     
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    1,251
    The Rigidbody component just overrides its GameObject's Transform so the world position and rotation come from the physics engine. The hierarchy doesn't have any effect as the final world pose is overriden. If you need some Rigidbody to move using another Rigidbody as reference, then you must do it explicitly. Some possible methods I can figure out:
    • Configure the child rigidbody as Kinematic, then use Rigidbody.MovePosition and Rigidbody.MoveRotation (from FixedUpdate) to ensure its position is related to the reference.
    • Attach both rigidbodies via Configurable Joint
    • Apply forces / torques (or even velocities) via Rigidbody.AddForce / Rigidbody.AddTorque to the child rigidbody based on the difference with the ideal position it should have based on the reference. Note that this is pretty much what a joint does, but doing it this way allows to configure behaviors not directly supported by the joint.
     
    Stranger-Games likes this.
  3. Stranger-Games

    Stranger-Games

    Joined:
    May 10, 2014
    Posts:
    290
    Thank you very much for your reply and details.

    I tried Fixed Joint approach and configuring the child rigidbody as kinematic and using Rigidbody.MovePositions. Both approaches had problems.

    First the fixed joint approach. The fixed joint works as parent/child as I wanted. But I wanted sometimes to move the child a little in its local space keeping the fixed joint effect. I did the following to change connectedAnchor but unfortunately the parent seems to move also for some reason. I don't want the parent to move in this code I only need the child to move in its local space while keeping the joint. (The parent is below i the gif)

    Code (CSharp):
    1. void Start () {
    2.         joint = GetComponent<FixedJoint>();
    3.         joint.autoConfigureConnectedAnchor = false;
    4. }
    5.  
    6. void FixedUpdate() {
    7.         var newAnchor = joint.connectedAnchor + Vector3.right * multiplier;
    8.         joint.connectedAnchor = newAnchor;
    9. }
    Fixed Joint connected anchor.gif

    I tried the same code with configurable joint but I get the same effect of the parent moving also opposite to child movement.

    The approach of Rigidbody.MovePosition has two main problems. First I don't want my child to be kinematic. I want if something hit my child that should also move the parent from the shock keeping the parent/child as it is. Fixed joint did this effect perfectly but had the problem above.
    The second problem with Rigidbody.MovePosition is that I don't have the child/parent movement in sync when the parent is accelerating/decelerating. As you can see when the parent at the bottom have force in one direction or opposite direction there's a slight delay in the child following it. The code I use is below the image.

    rigidbody.moveposition.gif

    Code (CSharp):
    1. void Start () {
    2.         rigid = GetComponent<Rigidbody>();
    3.         relativePos = transform.localPosition;
    4.         relativeRot = transform.localRotation;
    5.     }
    6.  
    7. private void FixedUpdate() {
    8.         Vector3 newPos = new Vector3();
    9.        
    10.         newPos = transform.parent.TransformPoint(relativePos);
    11.  
    12.         rigid.MovePosition(newPos);
    13.     }
    The same delay happens using the code below also

    Code (CSharp):
    1. private void FixedUpdate() {
    2.         Vector3 newPos = new Vector3();
    3.         var parentPos = transform.parent.GetComponent<Rigidbody>().position;
    4.         newPos = parentPos + relativePos;
    5.        
    6.         rigid.MovePosition(newPos);
    7.     }
    Thanks for advance.