Search Unity

Child GameObject not responding to angular drag

Discussion in 'Physics' started by zioth, Jan 26, 2020.

  1. zioth

    zioth

    Joined:
    Jan 9, 2019
    Posts:
    111
    My goal:
    My player object is a ball that rolls around based on user input and gravity.

    My problem:
    Because the player is rolling, its orientation changes constantly, so applying left/right forces to change its velocity is difficult.

    Current partial solution:
    I put the controller script on a spherical GameObject without a renderer. It has all three "freeze rotation" constraints. The rendered sphere is a child object, which has all three "freeze position" constraints, to keep it centered on the parent. The problem is, the child sphere doesn't respond to being dragged around by its parent -- it doesn't roll.

    Both child and parent have a sphere collider and a rigidbody, with angular drag set.

    Help?
    Any idea what I'm doing wrong? Another solution would be to keep a single GameObject, and figure out how to properly apply forces in script, so advice on that would be useful too.
     
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    Parented rigidbodies don't inherit anything. They totally behave as independent rigidbodies. What the Rigidbody component does is modifying the Transform's world position and rotation based on the physics interactions. Parenthood relationships don't have any influence here.

    You should be able to apply the forces to your rolling sphere normally, with Rigidbody.AddForce or Rigidbody.AddForceAtPosition. Both use world coordinates, so the result will be the same no matter the orientation of the sphere. Do not use Rigidbody.AddRelativeForce, as this one do expect the forces being expressed in local coordinates.
     
  3. zioth

    zioth

    Joined:
    Jan 9, 2019
    Posts:
    111
    That doesn't seem to be the case for me, but maybe I'm doing something else wrong. Here's the code I use to apply force (based on pressed arrow keys):
    Code (CSharp):
    1. private void FixedUpdate() {
    2.   Vector3 desiredMove = Vector3.ProjectOnPlane(
    3.     transform.right * -input.x,
    4.     m_GroundContactNormal
    5.   ).normalized;
    6.  
    7.   // m_GroundContactNormal comes from a SphereCast - hitInfo.normal
    8.   float angle = Vector3.Angle(m_GroundContactNormal, Vector3.up);
    9.   m_rigidBody.AddForce(desiredMove * angle, ForceMode.Impulse);
    10. }
    11.  
    When I press and hold an arrow key, the GameObject moves erratically, clearly being pushed in many different directions sequentially. It looks like it's always being pushed in the Player's "facing" direction, which changes as it rotates.
     
  4. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    That's because you're including "transform.right" in the calculation, which varies depending on the actual orientation of the ball. You should figure out a better reference that doesn't depend on the ball's rotation:
    • Vector3.right for the world's "right" direction.
    • Camera.main.transform.right for a direction based on your main camera.
    • any other transform or orientation you define explicitly for storing the player's orientation. This one may not move at all, you'd only manage its orientation based on your conditions.
     
    zioth likes this.
  5. zioth

    zioth

    Joined:
    Jan 9, 2019
    Posts:
    111
    Thank you, @Edy! `Camera.main.transform.right` was what I needed. That's so much simpler than the mess I had implemented.
     
    Edy likes this.