Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Move Rigidbody locally, while inheriting rotation from 'parent' rigidbody

Discussion in 'Physics' started by wantondalliance, Oct 16, 2019.

  1. wantondalliance

    wantondalliance

    Joined:
    Aug 22, 2018
    Posts:
    34
    I'm wondering what the best way to do this is:

    As an example here I have a blue block childed to a red block. As we'd all expect, rotating the parent transform rotates the child with it. The child can then be moved locally.

    What I want is to to do this in code BUT with the rigidbodies instead. So I want the blue block to rotate WITH the red one when the red block gets rotated. But of course, rigidbodies don't automatically inherit positions in that way.

    What would be the best way to do it?



    Here are my two scripts so far:


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class SetRbRotSlider : MonoBehaviour
    6. {
    7.     [Range(0f, 1f)] public float Value;
    8.  
    9.     public Vector3 AxisOfRotation;
    10.     public float AngleOfRotation;
    11.  
    12.     private Quaternion _initialRot;
    13.  
    14.     Rigidbody _rb;
    15.  
    16.     // Start is called before the first frame update
    17.     void Awake()
    18.     {
    19.         _rb = GetComponent<Rigidbody>();
    20.  
    21.         _initialRot = _rb.rotation;
    22.     }
    23.  
    24.     // Update is called once per frame
    25.     void FixedUpdate()
    26.     {
    27.         Vector3 offsetRot = AxisOfRotation * AngleOfRotation * Value;
    28.         Quaternion offsetRotQuat = Quaternion.Euler(offsetRot);
    29.         Quaternion targetRotQuat = _initialRot * offsetRotQuat;
    30.  
    31.         _rb.MoveRotation(targetRotQuat);
    32.     }
    33. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class SetRbPosSlider : MonoBehaviour
    6. {
    7.     [Range(0f, 1f)] public float Value;
    8.  
    9.     public Vector3 AxisOfMovement;
    10.     public float MoveRange;
    11.  
    12.     Rigidbody _rb;
    13.  
    14.     private Vector3 _offsetLastFrame;
    15.  
    16.     // Start is called before the first frame update
    17.     void Awake()
    18.     {
    19.         _rb = GetComponent<Rigidbody>();
    20.     }
    21.  
    22.     // Update is called once per frame
    23.     void FixedUpdate()
    24.     {
    25.         Vector3 offset = AxisOfMovement * MoveRange * Value;
    26.  
    27.         offset = transform.TransformDirection(offset);
    28.  
    29.         Vector3 offsetIncrement = offset - _offsetLastFrame;
    30.  
    31.         _rb.MovePosition(_rb.position + offsetIncrement);
    32.  
    33.         _offsetLastFrame = offset;
    34.     }
    35. }

    Note: I'm trying to do all of this with rigidbodies because it will be interacting with other rigidbodies.
     
    Last edited: Oct 16, 2019
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,497
  3. wantondalliance

    wantondalliance

    Joined:
    Aug 22, 2018
    Posts:
    34
  4. rebelincontrol

    rebelincontrol

    Joined:
    May 19, 2015
    Posts:
    30
    Did you end up finding a solid solution to this? I have a similar problem and I'm unable to get the rigidbodies behaving in a way similar to using the transform parent/child connection without rigidbodies!
     
  5. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,497
    The only way is using joints (or the kinematic workaround I referenced above). The Rigidbody component just overrides the Transform of the GameObject so it's ruled by physics in World coordinates. The parent/child connection hasn't any effect.