Search Unity

Rotating rigidbody around its LOCAL axis

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

  1. wantondalliance

    wantondalliance

    Joined:
    Aug 22, 2018
    Posts:
    34
    I've been searching how to do this for a while, and a few other people have asked the same thing but the answers are either very vague or aren't a solution.

    It has to be the rigidbody because other objects will interact with it. Imagine it's a seesaw that a ball can roll back and forth along:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class SetRotation : MonoBehaviour
    4. {
    5.     public InputSource InputSource; //Value of 0 - 1
    6.  
    7.     public Vector3 AxisOfRotation;
    8.     public float AngleOfRotation;
    9.  
    10.     public Vector3 _initialRotation;
    11.     public Vector3 _targetRotation;
    12.     public Vector3 _localRotAxis;
    13.     public Vector3 _targetRot;
    14.    
    15.     protected Rigidbody _rb;
    16.  
    17.     void Awake()
    18.     {
    19.         _rb = GetComponent<Rigidbody>();
    20.  
    21.         _initialRotation = _rb.rotation.eulerAngles;
    22.  
    23.     }
    24.  
    25.     void FixedUpdate()
    26.     {
    27.         Vector3 offsetRot = AxisOfRotation * AngleOfRotation * InputSource.Output;
    28.         _targetRot = _initialRotation + offsetRot;
    29.         Quaternion targetRotQuat = Quaternion.Euler(_targetRot);
    30.  
    31.         _rb.MoveRotation(targetRotQuat);
    32.     }
    33. }
    Weirdly this script works but only if AxisOfRotation is between a certain range, so (0, 0, 1) does work as intended, but (0, 1, 0) doesn't. I imagine this is to do with gimbal problems?

    Some people suggested using transform.InverseTransformDirection but I'm not really sure which vector exactly needs converting to local space...

    Any help would be much appreciated.
     
  2. Maeslezo

    Maeslezo

    Joined:
    Jun 16, 2015
    Posts:
    331
    To be honest, I don't understand what you are doing in your code.

    Something like this should work

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class SetRotation : MonoBehaviour
    4. {
    5.     [Range(0.0f, 1.0f)]
    6.     public float input; //Value of 0 - 1
    7.  
    8.     public Vector3 axisOfRotation;
    9.     public float angleOfRotation;
    10.  
    11.     public Quaternion initialRotation;
    12.     public Quaternion targetRot;
    13.  
    14.     protected Rigidbody rb;
    15.  
    16.     void Awake()
    17.     {
    18.         rb = GetComponent<Rigidbody>();
    19.         initialRotation = rb.rotation;
    20.     }
    21.  
    22.     void FixedUpdate()
    23.     {
    24.         float angle = angleOfRotation * input;
    25.         Quaternion q = Quaternion.AngleAxis(angle, axisOfRotation);
    26.         targetRot = initialRotation * q;
    27.         rb.MoveRotation(targetRot);
    28.     }
    29. }
    30.  
    rotation.gif
     
  3. wantondalliance

    wantondalliance

    Joined:
    Aug 22, 2018
    Posts:
    34
    Despite you not understanding my code, your script works perfectly, thank you - and thanks for the demonstration too! :)
     
  4. Maeslezo

    Maeslezo

    Joined:
    Jun 16, 2015
    Posts:
    331
    glad it helped!
     
  5. bdeniz1997

    bdeniz1997

    Joined:
    Jan 26, 2021
    Posts:
    15
    this seems to be solved but, i've had the same problem and i'll share my code. I needed to rotate an object with rigidbody.rotation, because if i directly changed its transform local rotation, it would glitch and still try to rotate through physics objects, and there was no way to rotate rigidbody on a local axis.
    Transforms have both local and world rotation. so i used it.
    what i did was something like this.
    Code (CSharp):
    1. Transform ts = transform; // make a new transform and copy current transform into that.
    2. ts.Rotate(new Vector3(0,0,1),Space.Self);// i rotate it on its Z local axis.
    3. GetComponent<Rigidbody>().rotation = ts.rotation; // set rigidbody's rotation to the created transform. Note that i set its local rotation by space.self but, used ts.rotation, which is world rotation.
     
  6. b00dle

    b00dle

    Joined:
    Nov 18, 2015
    Posts:
    3
    I haven't tested your code, but just so you know, you are merely creating a shallow copy of your transform. Meaning, your second line of code will in fact change your original transform. Maybe you aren't observing your initially outlined problem, because you are applying the rotation again on the rigidbody directly after.