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

Is rotation that hard?

Discussion in 'Scripting' started by Iqo, Feb 1, 2020.

  1. Iqo

    Iqo

    Joined:
    Feb 1, 2020
    Posts:
    2
    I am working on a game where the player's head can rotate within a 90-degree rotation. (45 above 0, and 45 below). This movement is based on pressing and holding the W key or the S key for going down. I have tried so many different things to try and get this to work but it is surprising that there is no documentation for how to overcome.
    Code (CSharp):
    1.  
    2. if (Input.GetKey(KeyCode.W))
    3.                 {
    4.  
    5.                     Vector3 rotationBound = transform.localRotation.eulerAngles;
    6.                     rotationBound.z = Mathf.Clamp(rotationBound.z - m_rotationSpeed, 45, 315);
    7.  
    8.                     transform.localRotation = Quaternion.Euler(rotationBound);
    9.  
    10.                 }
    11.                 if (Input.GetKey(KeyCode.S))
    12.                 {
    13.                     Vector3 rotationBound = transform.localRotation.eulerAngles;
    14.                     rotationBound.z = Mathf.Clamp(rotationBound.z + m_rotationSpeed, 45, 315);
    15.  
    16.                     transform.localRotation = Quaternion.Euler(rotationBound);
    17.                 }
    18.  
    This function makes it so the head rotates everywhere BUT the place where I want it to rotate within. Please help
    (The player is facing left by the way)
     
  2. diXime

    diXime

    Joined:
    Oct 2, 2018
    Posts:
    162
    Hello,
    To my experience, rotations can be rather tricky to handle for a few reasons. Here are a few leads for you to explore to find the reasons why your head rotation script doesn't work as intended.
    • When using Blender, all of the axis are messed up. There is a way to correct this. And yes, I keep this link in my favorites. (Most of my problems with rotations comes from this, because LookAt usually handles the rest decently)
    • Quaternions (rotations in 3D space) are extremely counter intuitive. If you want an AMAZING resource to understand them, 3Blue1Brown has participated in an amazing interactive video with Ben Eater.
    • It's not because of Unity, but there is a huge gap between what you are seeing (or want to see) and what you are doing (or want to do). The engine has no way to know where the eyes are, thus "facing towards something" is, to it, an angle you can get with transform.LookAt(), but it can't guarantee you that "look" is what you meant to do.
    • Be careful with EulerAngles (I see you use them a lot). It is known to have Gimbal Lock, which is a way to say you lose a degree of freedom. To make it quick, it's possible for your axis of rotation to align, and also linear rotations of axis give non-linear rotations in space. More so, there is more than one way to express a given rotation in 3D space with euler angles, they are not consistent.
    • Rotation is one problem, smooth rotation is another.
    • Unity can't move around the pivot around which you rotate your object. You must set it (for good...) in your 3D software. There are ways to set the pivot to center or pivot with code, but results are inconsistent at best.

    These are the reasons that comes to my mind why rotations are tricky, and fixing other people's problems with rotations are even more problematic. Without visual feedback, one must be quite experienced with the matter to solve code problems.

    For your problem, I see you only put rotationBound in Quaternion.Euler. I'm not 100% sure, but you seem to use current rotation to set head rotation, which looks like interference upon reading, you should try to put the x and y before (0, 0, rotationBounds.z), since you only want your head to rotate around the Z axis (or x if I haven't focused enough, it's 2 am here). See the manual. If it doesn't fix it, make sure your mesh is rotated correctly, or try with negative values for your bounds (in case the sign switch is straight ahead, the limit up is + the limit down is -, or left to right)
     
    Last edited: Feb 2, 2020
    Kurt-Dekker likes this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    What @diXime says above is all good stuff! Let me add a few things:

    In your model/camera setup, put in extra GameObjects parented to each other in a long chain. Use each Transform of those GameObjects to drive only one axis of rotation per GameObject.

    Code (csharp):
    1. // make your GameObject hierarchy like this:
    2. PlayerRoot
    3.     OffsetToEyes
    4.         LookLeftRightGimbal <- drive this one around the Y axis only
    5.             LookUpDownGimbal <- drive this one around the Y axis
    6.  
    For look up/down, use a single float value and clamp it between -45 and 45, and only change that variable with your W/S keys.

    Now when you set the
    .rotation
    , instead you are going to be setting the
    .localRotation
    of the LookUpDownGimbal Transform.

    Build it up a piece at a time. You'll find it's a much easier process to keep it all looking the right way.

    Blender does indeed turn all the axes around, but you can tear chunks off your model and move it to a fresh Prefab for specific parenting/orienting.
     
  4. Iqo

    Iqo

    Joined:
    Feb 1, 2020
    Posts:
    2
    Hi, thanks for your help! I managed to fix it another way, through the use of a million if-else checks. It was also a 2D game, so most of the 3D help didn't really apply sorry :/