# Quaternion Angles messed up

Discussion in 'Scripting' started by asd234w4r5, May 18, 2018.

1. ### asd234w4r5

Joined:
Oct 4, 2012
Posts:
653
Hello everyone!

I am trying to rotate an object around its X-Axis and make it stop at certain points. So lets say, there is a sentence with 5 words, these 5 words get wrapped around this capsule and you can later select them. My code for the rotation is here, while the important part is the last one where the angle gets calculated by the "steps"

Code (CSharp):
1.
2. float steps = 360 / Bandit_Game.gameBandit.answerArray.Length;
3. //The answers are the split up text, like 5 words
4.
5. private void Update()
6.     {
7.         RaycastHit hit;
8.         Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
9.
10.         if (Physics.Raycast(ray, out hit))
11.         {
12.             if (hit.collider.GetComponent<CapsuleCollider>().transform.IsChildOf(transform))
13.             {
14.                 cardSelected = true;
15.             }else{
16.                 cardSelected = false;
17.             }
18.         }
19.
20.         if (Input.GetMouseButtonDown(0) && cardSelected)
21.         {
22.             differenceX = 0.0f;
23.         }
24.         else if (Input.GetMouseButton(0) && cardSelected)
25.         {
26.             differenceX = Mathf.Abs(lastX - Input.GetAxis("Mouse Y"));
27.
28.             if (lastX > Input.GetAxis("Mouse Y"))
29.             {
30.                 direction = -1;
31.                 transform.Rotate(Vector3.right, -differenceX);
32.             }
33.
34.             if (lastX < Input.GetAxis("Mouse Y"))
35.             {
36.                 direction = 1;
37.                 transform.Rotate(Vector3.right, differenceX);
38.             }
39.
40.             lastX = -Input.GetAxis("Mouse Y");
41.         }
42.         else
43.         {
44.             if (differenceX > 0.5f)
45.             {
46.                 differenceX -= 0.1f;
47.                 transform.Rotate(Vector3.right, differenceX * direction);
48.             }
49.             else if (differenceX < -0.5f)
50.             {
51.                 differenceX += 0.1f;
52.                 transform.Rotate(Vector3.right, differenceX * direction);
53.             }
54.             else
55.             {
56.                 float vecX = Mathf.Round(transform.eulerAngles.x / steps) * steps;
57.
58.                 transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.Euler(new Vector3(vecX, transform.eulerAngles.y, transform.eulerAngles.z)), Time.deltaTime * 50f);
59.             }
60.         }
61.
62.         Debug.Log(transform.rotation.x);
63.     }
What is happening now: I have 5 * 72 degree steps, which work on the Quaternion between 0 and 1, but as soon as I turn the rotation over 180 degrees, it will start to like "mirror" the positions and it stops between those points instead. I hope you understand, what I mean, otherwise just ask and I get more in detail.

At least, what I wanted to achieve and couldn't figure out is
• Calculate the steps (360 / words)
• Generate the words around the capsule with their right rotation (this is working)
• Snap the rotation to the nearest "step" calculated in the first bullet

I hope, you can help me, figure it out. I was trying to work in quaternion world only, but this is unreliable, going through eulerAngles didn't do the trick neither for now.

Thank you!

Joined:
Oct 4, 2012
Posts:
653
Anyone?

3. ### methos5k

Joined:
Aug 3, 2015
Posts:
8,714
Maybe this is helpful?
Code (csharp):
1. public class Test1 : MonoBehaviour
2. {
3.     [SerializeField]
4.     int steps = 0;
5.     float stepval = 0f;
6.     [SerializeField]
7.     float rotval = 0;
8.     [SerializeField]
9.     int currentStep = 0;
10.     [SerializeField]
11.     float dragRotationSpeed = 5;
12.
13.     void Start()
14.     {
15.         stepval = 360 / steps;
16.     }
17.
18.     void Update()
19.     {
20.         float mouserot = Input.GetAxis("Mouse Y") * Time.deltaTime * dragRotationSpeed;
21.         rotval += mouserot;
22.
23.         while(rotval > 1)
24.         {
25.             currentStep++;
26.             if (currentStep >= steps) currentStep = 0;
27.             rotval -= 1;
28.         }
29.         while(rotval < 0)
30.         {
31.             currentStep--;
32.             if (currentStep < 0) currentStep = steps - 1;
33.             rotval++;
34.         }
35.
36.         // safely ignore the z with '90'
37.         transform.rotation = Quaternion.Euler(currentStep * stepval, 0, 90);
38.     }
39. }

4. ### asd234w4r5

Joined:
Oct 4, 2012
Posts:
653
I'll give it a try tomorrow! Thank you for sharing your own script I'll let you know if it did work!

5. ### methos5k

Joined:
Aug 3, 2015
Posts:
8,714
Sure, say I drag the mouse up the screen, it keeps adding to the rotation value, and when it's greater than 1 it increases the value of 'current step', which is then used to calculate current step * step value for your rotation.

When you get around to trying it, let me know if I understood it correctly.

6. ### asd234w4r5

Joined:
Oct 4, 2012
Posts:
653
hey there @methos5k , did not forget to check your script and it helped me well in some steps Thanks again. Here is the script of my manager for that single game:

Code (CSharp):
1. private void Update()
2.     {
3.         RaycastHit hit;
4.         Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
5.
6.         if (Input.GetMouseButton(0))
7.         {
8.             if (Physics.Raycast(ray, out hit))
9.             {
10.                 if (hit.collider.GetComponent<Bandit_Card>())
11.                 {
12.                     hitBanditCard = hit.collider.GetComponent<Bandit_Card>();
13.
14.                     float mouserot = Input.GetAxis("Mouse Y") * Time.deltaTime * 5f;
15.                     differenceY += mouserot;
16.                 }
17.             }
18.         }
19.
20.         if(Input.GetMouseButtonUp(0))
21.         {
22.             while (differenceY > 1)
23.             {
24.                 hitBanditCard.currentStep++;
25.                 //if (hitBanditCard.currentStep >= hitBanditCard.steps) hitBanditCard.currentStep = 0;
26.                 differenceY--;
27.             }
28.             while (differenceY < 0)
29.             {
30.                 hitBanditCard.currentStep--;
31.                 //if (hitBanditCard.currentStep < 0) hitBanditCard.currentStep = hitBanditCard.steps - 1;
32.                 differenceY++;
33.             }
34.
35.             if (Physics.Raycast(ray, out hit))
36.             {
37.                 if (hit.collider.GetComponent<Bandit_Check>())
38.                 {
39.                     CheckCardMatch();
40.                 }
41.             }
42.         }
43.     }
And then I just let the thing rotate around the current rotation with this script
Code (CSharp):
1. private void Update()
2.     {
3.         if(!randomRotationOn)
4.             rotatorObject.localRotation = Quaternion.Slerp(rotatorObject.localRotation, Quaternion.Euler(currentStep * steps, 0, 0), Time.deltaTime * 15f);
5.
6.         currentRotation = Quaternion.Angle(rotatorObject.localRotation, correctRotation);
7.     }
8.
9.     public IEnumerator RotateRandomly()
10.     {
11.         currentStep = Mathf.Floor(Random.Range(0, 360) / steps);
12.         randomRotation = Quaternion.Euler(currentStep * steps, 0, 0);
13.
14.         float timeWaiting = 5f;
15.         while (timeWaiting > 0)
16.         {
17.             rotatorObject.Rotate(Vector3.right, 10f * timeWaiting);
18.             timeWaiting -= 0.1f;
19.             yield return rotatorObject.localRotation;
20.         }
21.
22.         while (Quaternion.Angle(rotatorObject.localRotation, randomRotation) > 5f)
23.         {
24.             rotatorObject.localRotation = Quaternion.Slerp(rotatorObject.localRotation, randomRotation, Time.deltaTime * 2f);
25.             yield return rotatorObject.localRotation;
26.         }
27.         randomRotationOn = false;
28.     }