# Help Wanted Can't quite understand quaternion rotation (euler angles)

Discussion in 'Scripting' started by Adriano1499, Dec 14, 2020.

Joined:
May 1, 2019
Posts:
3
Hi, I'm currently working on a puzzle game, the part where I'm struggling - a cog which you can rotate. It's a 3d model and upon clicking on the left side it should rotate counter-clockwise by 40 degrees, opposite on the right side. Anyway the rotation happens on the y-axis, it all works fine until the y rotation goes into negative angles (-40) in that case instead of rotating to the left it rotates back to 0. Here's the code in the Move method called by Update :
``StartCoroutine(RotateGearA(Vector3.right * 40, 1));``

And the coroutine here:

Code (CSharp):
1. IEnumerator RotateGearA(Vector3 byAngles, float inTime) {
2.         isMoving = true;
3.         var fromAngle = cogA.transform.rotation;
4.         var toAngle = Quaternion.Euler(cogA.transform.eulerAngles + byAngles);
5.         for(var t = 0f; t < 1; t += Time.deltaTime/inTime) {
6.             cogA.transform.rotation = Quaternion.Lerp(fromAngle, toAngle, t);
7.             yield return null;
8.         }
9.     }
I'm not sure whether I should implement an if-else statement in the Move() method to handle the edge cases or if there's another approach?

Last edited: Dec 14, 2020

Joined:
May 1, 2019
Posts:
3
PS. If it helps that coroutine is from my previous project where the cogs were 2D sprites, it worked fine there

3. ### Ray_Sovranti

Joined:
Oct 28, 2020
Posts:
172
Euler angles are pretty terrible to work with because it's not mathematically possible to reliably convert a Quaternion to a single set of Euler angles. So the conversion algorithm has to choose which of the possible conversions to use, and as the rotation changes this is not consistent. So you'll get random jumps here and there. Further reading.

You can avoid these problems by either:
A) storing your rotation as a Vector3 on your own, using Quaternion.Euler as a one-way street (i.e. never convert a Quaternion to Euler angles);
B) use Quaternion math exclusively
C) for something like this, don't bother with coding rotations at all; just make a rotation animation, and trigger that animation in script.

Joined:
May 1, 2019
Posts:
3
Thanks for the info, it appears I fixed it by using the Quaternion operator *

Code (CSharp):
1. IEnumerator RotateGearA(Vector3 byAngles, float inTime) {
2.         isMoving = true;
3.         var fromAngle = cogA.transform.rotation;
4.         // var toAngle = Quaternion.Euler(cogA.transform.eulerAngles + byAngles);
5.         var toAngle = fromAngle * Quaternion.Euler(byAngles);
6.         for(var t = 0f; t < 1; t += Time.deltaTime/inTime) {
7.             cogA.transform.rotation = Quaternion.Lerp(fromAngle, toAngle, t);
8.             yield return null;
9.         }
10.     }
But for the future I'll stay away from these evil euler angles 5. ### Ray_Sovranti

Joined:
Oct 28, 2020
Posts:
172
The important thing is to always avoid Quaternion -> Euler conversion, and your new code does avoid that. There's no problem converting Euler to Quaternion. unityunity