Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by MLM · Jan 08, 2014 at 08:38 PM · rotationtransformquaternionrotateeulerangles

Rotation Jumping values (0 to 180)

I am having an issue where eulerAngles.y is returning a Y rotation value that jumps when I move the character head up and down (X axis).

So when I move the head up (above green line), eulerAngles.y returns 0. But when I move down (below green line), eulerAngles.y returns 180. Keep in mind that moving the head up and down rotates around the X axis.

Check out the Video (YouTube) explaining the issue.

ou can see in the second picture that the local transform and rotation for the head are not default and are a bit rotated.

Head Up Down

Head Transform

The Lines coming from the head are just gizmos created as so:

 Gizmos.color = Color.red;
 Gizmos.DrawLine(headTransform.position, headTransform.position + headTransform.up*3);
 
 Gizmos.color = Color.green;
 Vector3 forward = headTransform.up;
 Gizmos.DrawLine(headTransform.position, headTransform.position + (new Vector3(forward.x, 0, forward.z)*3));


I know that `eularAngles` has a rotation order but how do I get the Y rotation in world space that I can apply to any object and it will point in the same direciton.


My goal is to make the body turn to where the head is looking and have the head counteract the body motion so they are aligned. Although I am having other issues, this is just one I am stuck on why this is happening. When I add the code below, the character just spins around and around.

 // Make the body rotate to where our head is pointing
 bodyTransform.eulerAngles = new Vector3(bodyTransform.eulerAngles.x, headTransform.eulerAngles.y, bodyTransform.eulerAngles.z);
 
 // Counter-act the body by rotating the head back into place
 headTransform.eulerAngles = new Vector3(headTransform.eulerAngles.x, bodyTransform.eulerAngles.y, headTransform.eulerAngles.z);



Update:

I tried what @robertbu suggested using `Quaternion.LookRotation` but I am having trouble getting the desired head, body alignment with the below code. I tried messing with the upwards parameter but nothing works. "Z axis will be aligned with forward and the Y axis with upwards" (Unity documentation) so I am wondering if the transform on the head is messing with it. I am assuming the first part is right because it does turn the body in the direction the head is pointing but I am failing at making the head align with the body to stop it from spinning.

 // Make the body rotate to where our head is pointing
 /* */
 Vector3 headForwardDirection = headTransform.up;
 headForwardDirection.y = 0f;
 Quaternion qTo = Quaternion.LookRotation(headForwardDirection);
 bodyTransform.rotation = qTo;
 /* */

 // Counter-act the body by rotating the head back into place
 /* */
 Vector3 bodyForwardDirection = bodyTransform.forward;
 bodyForwardDirection.y = 0f;
 Quaternion qTo2 = Quaternion.LookRotation(bodyForwardDirection);
 headTransform.rotation = qTo2;
 /* */


Update #2 (Solution):

Just got the project working as expected with the advice of @robertbu of fixing my model head pivot/axis so that Z points forward and Y up. I added a empty/null and parented the head bone.

Here is the script I used to complete the align. It is a combination of a head look and align when moving.

 using UnityEngine;
 using System.Collections;
 
 public class HeadMoveScript : MonoBehaviour {
 
     public Transform headTransform; // Used to rotate the head
     public Transform bodyTransform; // Used to rotate the body when head rotation limit reached
     public Transform testTransform;
 
     public GameObject cMotorGameObject;
 
     public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }
     public RotationAxes axes = RotationAxes.MouseXAndY;
     public float sensitivityX = 15F;
     public float sensitivityY = 15F;
     
     public float minimumX = -360F;
     public float maximumX = 360F;
     
     public float minimumY = -60F;
     public float maximumY = 60F;
 
     float rotationX = 0F;
     float rotationY = 0F;
     
     Vector3 originalForward;
     Vector3 originalUp;
     Vector3 originalRight;
 
     Quaternion originalRotation;
     
     void Update ()
     {
         rotationX += Input.GetAxis("Mouse X") * sensitivityX;
         rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
 
         // Rotate the body when we reach the rotation limits
         if (axes == RotationAxes.MouseXAndY || axes == RotationAxes.MouseX)
             bodyTransform.localEulerAngles = new Vector3(bodyTransform.localEulerAngles.x, bodyTransform.localEulerAngles.y + ClampExcess(rotationX, minimumX, maximumX), bodyTransform.localEulerAngles.z);
 
         rotationX = Mathf.Clamp(rotationX, minimumX, maximumX);
         rotationY = Mathf.Clamp(rotationY, minimumY, maximumY);
 
 
 
         Quaternion xQuaternion = Quaternion.AngleAxis(rotationX, originalUp);
         Quaternion yQuaternion = Quaternion.AngleAxis(rotationY, -originalRight);
 
         if (axes == RotationAxes.MouseXAndY)
         {
             headTransform.localRotation = originalRotation * xQuaternion * yQuaternion;
         }
         else if (axes == RotationAxes.MouseX)
         {
             headTransform.localRotation = originalRotation * xQuaternion;
         }
         else
         {
             headTransform.localRotation = originalRotation * yQuaternion;
         }
 
 
         /* */
         Vector3 moveVelocity = cMotorGameObject.GetComponent<CharacterMotor>().movement.velocity;
         // When we start to move forward, make sure we run in the direction our head is pointing
         if(Mathf.Abs(moveVelocity.x) > 0 || Mathf.Abs(moveVelocity.z) > 0)
         {
             // Make the body rotate to where our head is pointing
             /* */
             Vector3 headForwardDirection = headTransform.forward;
             headForwardDirection.y = 0f;
             Quaternion qTo = Quaternion.LookRotation(headForwardDirection);
             bodyTransform.rotation = qTo;
             /* */
             
 
             // Counter-act the body by rotating the head back into place
             /* */
             Vector3 bodyForwardDirection = bodyTransform.forward;
             bodyForwardDirection.y = 0f;
             Quaternion qTo2 = Quaternion.LookRotation(bodyForwardDirection) * Quaternion.AngleAxis(rotationY, -originalRight);
             headTransform.rotation = qTo2;
             /* */
 
             // Also reset the look rotation of the head
             // So we do not jump back after a new loop
             rotationX = 0F;
         }
         /* */
 
     }
     
     void Start()
     {
         originalForward = headTransform.forward;
         originalUp = headTransform.up;
         originalRight = headTransform.right;
         originalRotation = headTransform.localRotation;
     }
 
 
     void OnDrawGizmos()
     {
         Gizmos.color = Color.red;
         Gizmos.DrawLine(headTransform.position, headTransform.position + headTransform.forward*3);
         
         Gizmos.color = Color.green;
         Vector3 forward = headTransform.forward;
         Gizmos.DrawLine(headTransform.position, headTransform.position + (new Vector3(forward.x, 0, forward.z)*3));
     }
 
 
 
     // Returns the excess from min or max
     float ClampExcess(float value, float min, float max)
     {
         if(value < min)
             return value - min;
         else if(value > max)
             return value - max;
 
         return 0;
     }
 
 }




Comment
Add comment · Show 3
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Anxo · Jan 08, 2014 at 09:10 PM 0
Share

Hats off for well presented question.

avatar image TimBorquez · Jan 08, 2014 at 09:26 PM 0
Share

i think that may be called gimbal lock, maybe google that?

avatar image MLM · Jan 09, 2014 at 01:17 AM 0
Share

@Anxoss If you like the question, consider upvoting it. It seems that this SE type site lacks voting responses.

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by robertbu · Jan 08, 2014 at 10:12 PM

Euler angles are derived from the Quaternion. There are multiple euler angle for any given physical rotation, and Unity may change them on you. Here is a simple example:

 transform.eulerAngles = new Vector3(180,0,0);
 Debug.Log(transform.eulerAngles);

The values output are (0,180,180). So that means if you were only reading the 'y' value, you would see an immediate 180 degree shift even though the 'y' orientation did not change.

The typical way to solve this problem is to work with either Quaternion.LookRotation() or Transform.LookAt() depending on how you are working with your code. So you would do something like:

 Vector3 direction = head.forward;
 direction.y = 0.0;
 Quaternion qTo = Quaternion.LookRotation(direction);

This takes the forward vector of the head, eliminates any elevation and then calculates a rotation to look in that direction.

To rotate the body over time, to face this direction, you can use Quaternion.RotateToward() or Quaternion.Slerp() depending on whether you want eased movement or not:

 transform.rotation = Quaternion.RotateTowards(transform.rotation, qTo, speed * Time.deltaTime);
Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image MLM · Jan 09, 2014 at 01:16 AM 0
Share

Check out the update in the OP. I can get some LookRotation bits working but I can't get the full picture to come together with the body moving to the head rotation and the head moving back so that both have the same rotation. Thanks for the reply!

avatar image robertbu · Jan 09, 2014 at 02:15 AM 0
Share

Why this line?:

 Vector3 headForwardDirection = headTransform.up

Is the head model not built correctly? That is, the front of the face should be the forward of the head. If you have rotation (0,0,0), then the face should look at positive 'z'. If this is not true, then all sorts of ugly things can happen. If this is what is going on, then it can be fixed in the modeling program, by using an empty game object, or by using an editor script.

avatar image MLM · Jan 09, 2014 at 02:27 AM 0
Share

Check this image to see that the y-axis is pointing forward in Unity when using local. It is not the right way in Cinema 4d but the problem is that Unity uses Left hand Y-up Axis and C4D exports as Right hand Y-up Axis (see this thread and my small script that solves it for simple bone rig). I am not using a simple bone rig and ins$$anonymous$$d Cinema 4D Character object which makes it really easy to create biped rigs with both F$$anonymous$$ and I$$anonymous$$ handles but I do not think I can change the pivot/Axis. There is a axis tool in C4D but I can't with this special object/bone.

Edit: I used a empty null around the special bones (in C4D) and zeroed it out so it is correct. I then use that parent null as the normal head transform. I have not gotten the alignment code to work but now we have a good starting point.

Edit #2: I just got it working (see update #2 in op). One of my issues was not resetting the mouse look x rotation. No transition/slerp but the concept is completed.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

20 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Object wont rotate in the opposite direction 1 Answer

How do you smoothly transition/Lerp into a new rotation? 3 Answers

Rotate object to where aiming 1 Answer

How to instantiate on custom rotation? 1 Answer

Player character X rotation going haywire on game start 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges