Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Setting Default Rotations

Discussion in 'Scripting' started by DRRosen3, May 16, 2021.

  1. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    I've got the following code handling the rotation of a child object on the game's player object.

    Code (CSharp):
    1. private void Update()
    2. {
    3.     input = Mouse.current.delta.ReadValue();
    4. }
    5. private void LateUpdate()
    6. {
    7.     if (axes == RotationAxes.MouseXAndY)
    8.     {
    9.         vertical += input.y * sensitivityY;
    10.         vertical = Mathf.Clamp(vertical, minimumY, maximumY);
    11.  
    12.         horizontal += input.x * sensitivityX;
    13.         horizontal = Clamp(horizontal, minimumX, maximumX);
    14.  
    15.         if (rotateObject == null)
    16.             transform.rotation = Quaternion.Euler(vertical, horizontal, 0.0f);
    17.         else
    18.         {
    19.             //Normally vertical would be applied to the X axis, but because of the bone's orientation, we apply it to the Z axis.
    20.             rotateObject.transform.rotation = Quaternion.Euler(0.0f, horizontal, vertical);
    21.         }
    22.     }
    23.     else if (axes == RotationAxes.MouseX)
    24.     {
    25.         horizontal += input.x * sensitivityX;
    26.         horizontal = Mathf.Clamp(horizontal, minimumX, maximumX);
    27.  
    28.         if (rotateObject == null)
    29.             transform.rotation = Quaternion.Euler(0.0f, horizontal, 0.0f);
    30.         else
    31.             rotateObject.transform.rotation = Quaternion.Euler(0.0f, horizontal, 0.0f);
    32.     }
    33.     else
    34.     {
    35.         vertical += input.y * sensitivityY;
    36.         vertical = Mathf.Clamp(vertical, minimumY, maximumY);
    37.  
    38.         if (rotateObject == null)
    39.             transform.rotation = Quaternion.Euler(vertical, 0.0f, 0.0f);
    40.         else
    41.         {
    42.             //Normally vertical would be applied to the X axis, but because of the bone's orientation, we apply it to the Z axis.
    43.             rotateObject.transform.rotation = Quaternion.Euler(0.0f, 0.0f, vertical);
    44.         }
    45.     }
    46. }
    47.  
    48. private float Clamp(float value, float min, float max)
    49. {
    50.     if (value < min || value > max)
    51.         return 0.0f;
    52.     else
    53.         return value;
    54. }
    The Clamp method above is because the Mathf.Clamp method doesn't allow the rotation to go back to 0 once a full circle is made.

    Now the problem I'm having is that when the player presses the appropriate input to begin rotating this object, it automatically turns it to a weird orientation. I'm assuming this is because the default values of "vertical" and "horizontal" are 0.0f to start. Question is, how can I get the appropriate rotation values from the "rotateObject" in order to set "vertical" and "horizontal" to the correct default values (which would be whatever the values of the rotateObject's rotation is when this script is enabled.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,749
    This isn't generally possible due to gimbal lock.

    The .eulerAngles properties you can read from a Quaternion are NOT deterministic in the sense that more than one combination of Euler angles produces identical Quaternions. When you begin doing single-axis arithmetic you will encounter different points when it gimbal-locks-out. If you are not particularly excessive in your initial rotation, you might get away with it.

    If you have something with a wonky arbitrary orientation, put a parent Transform in above it that is Quaternion.identity so you can start from zeroes.
     
  3. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Gah... I was afraid that it was going to be an "impossible" task. Can't put a parent on it, because it's a bone. So I suppose my only other option is to create an empty Transform to make the bone look at, and manipulate that instead?
     
  4. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    It'll be fine to use the euler angles for the starting values because you're rebuilding the rotation every frame anyways. Do it in OnEnable, Start or whatever's appropriate.

    Code (csharp):
    1.  
    2. void OnEnable()
    3. {
    4.    Transform target = (rotateObject == null) ? transform : rotateObject;
    5.  
    6.    horizontal = target.localEulerAngles.y;
    7.    vertical = target.localEulerAngles.x;
    8. }
    9.  
     
  5. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    You know, I tried doing that before but it still resulted in the default rotation being wrong. Thanks to your suggestion I went in and tried it again, and it's still not right. However, I came up with the idea of just manually setting the default values, but setting them to an offset. This way, after the script is enabled, on the very first LateUpdate, it zeros out the rotation. Looks like this...

    Code (CSharp):
    1. private void OnEnable()
    2. {
    3.     if (rotateObject != null)
    4.     {
    5.         vertical = -90.0f;
    6.         horizontal = -90.0f;
    7.     }
    8. }