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

Need help with Quaternions.

Discussion in 'Scripting' started by WingNova, Mar 28, 2018.

  1. WingNova

    WingNova

    Joined:
    Aug 10, 2016
    Posts:
    7
    I am trying to make a slot machine demo but I am having issues with the wheels spin. The wheels will stop in the correct spot but how they get there is the issue. The order of how the wheel should be is;

    (wheels are already spinning)
    1.Push play button
    2.It picks the spot to land on
    3.checks to see if the wheel is past the point selected or to close to the target degrees
    --if to close(45 degrees) will continue to Transfrom.Rotate till 245 degrees have past
    --if past point selected will continue to Transfrom.Rotate till 180 degrees have past
    --if not then stops Transfrom.Rotate
    4. Starts the slerp to target rotation

    The problems I am having are, that the wheel will move slightly past the target degrees and reverse the wheel in the opposite direction to get to the intended degrees. Also I am having a difficulty time in how to check if I am to close to the target degrees(45 or less) causing the wheel to stop to fast. I think the math is wrong but I have no idea how to fix it. I am trying to use the dot product of the angle/degrees that I want vs the current angle/degrees of the wheel. Maybe I am going about this the wrong way. If any one has an idea about doing it a better way i would love to hear it or just fixing my code.

    Code (CSharp):
    1.  
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using UnityEngine;
    6.  
    7. public class Wheels : MonoBehaviour {
    8.  
    9.     Quaternion wheels;
    10.     public float speed = 800;
    11.     public bool freeSpin = false;
    12.     public float setAngle = 90;
    13.     public float currentWheel;
    14.     private bool moving = true;
    15.     public float timer = 3;
    16.     private bool timerOn = false;
    17.  
    18.     // Use this for initialization
    19.     void Start ()
    20.     {
    21.         Manager.PlayWheel += startWheel;
    22.         currentWheel = transform.rotation.x;
    23.     }
    24.  
    25.     void startWheel()
    26.     {
    27.         freeSpin = !freeSpin;
    28.         print(freeSpin);
    29.     }
    30.     // Update is called once per frame
    31.     void FixedUpdate()
    32.     {
    33.      
    34.         if(moving)
    35.             Spin();
    36.     }
    37.  
    38.     private void PickRandom()
    39.     {
    40.         setAngle = UnityEngine.Random.Range(0, 360);
    41.         setAngle = (int) setAngle / 45;
    42.         setAngle *= 45;
    43.     }
    44.  
    45.     void Spin()
    46.     {
    47.         if (freeSpin)
    48.         {
    49.             PickRandom();
    50.             transform.Rotate(Vector3.back * Time.deltaTime * speed);
    51.         }
    52.         else
    53.         {
    54.  
    55.             StopWheel();
    56.         }
    57.     }
    58.  
    59.     private void StopWheel()
    60.     {
    61.         Quaternion target = Quaternion.Euler(0, 90, setAngle);
    62.         float dot = Quaternion.Dot(transform.rotation, target);
    63.         if (0 < dot && dot < 8)
    64.         {
    65.             transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime * 5);
    66.          
    67.         }
    68.         else
    69.         {
    70.             transform.Rotate(Vector3.back * Time.deltaTime * speed);
    71.             //print("Tryed to go backwards");
    72.  
    73.         }
    74.     }
    75. }
    76.  


    wheel 3-4.PNG
     
    Last edited: Mar 28, 2018
    Homicide likes this.
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    Don't use the actual transform rotation stuff to rotate a transform like this.

    Instead keep a float number indicating the angle (from 0 to 360 degrees... it wraps around just fine) of each reel, and advance that number through at the speed you want the wheel to turn.

    Finally each frame after you have advanced or retracted each reel to where it should be, use that float number to intentionally drive the actual rotation of the object, like so:

    Code (csharp):
    1.  int SpeedOfRotation = 100.0f;
    2.  AngleValue += SpeedOfRotation * Time.deltaTime;   /* AngleValue is the value of each particular reel */
    3.  ReelTransform.rotation = Quaternion.Euler( AngleValue, 0, 0);  // "drive" the angle to the rotation, in this case around the X axis
    4.  
    That way you can spin both ways, it never gets lossy, etc.
     
  3. WingNova

    WingNova

    Joined:
    Aug 10, 2016
    Posts:
    7
    Thank you for your reply. You post inspired me to figure it out. I got it to work 100% of the time now and here is how it works.

    1.lets it spin
    2.checks if 120 degrees out from target
    3.then slerps the rest of the way to target

    Here is the finished code

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class Wheels : MonoBehaviour {
    7.  
    8.     public float speed = 600;
    9.     public bool freeSpin = false;
    10.     public float preAngle;
    11.     public float setAngle = 90;
    12.     private bool moving = true;
    13.     public float timer = 3;
    14.     private bool timerOn = false;
    15.     private bool hitPre = false;
    16.    
    17.  
    18.     // Use this for initialization
    19.     void Start ()
    20.     {
    21.         Manager.PlayWheel += startWheel;
    22.     }
    23.    
    24.     void startWheel()
    25.     {
    26.         freeSpin = !freeSpin;
    27.        
    28.         print(freeSpin);
    29.     }
    30.     // Update is called once per frame
    31.     void FixedUpdate()
    32.     {
    33.         if(moving)
    34.             Spin();
    35.     }
    36.  
    37.     private void PickRandom()
    38.     {
    39.         setAngle = UnityEngine.Random.Range(0, 360);  
    40.         setAngle = (int) setAngle / 45;
    41.         setAngle *= 45;
    42.  
    43.         preAngle = setAngle + 120;
    44.     }
    45.  
    46.     void Spin()
    47.     {
    48.         if (freeSpin)
    49.         {
    50.             hitPre = false;
    51.             PickRandom();
    52.             Spinning();
    53.         }
    54.         else
    55.         {
    56.             StopWheel();
    57.         }
    58.     }
    59.  
    60.     private void StopWheel()
    61.     {
    62.         Quaternion preTarget = Quaternion.Euler(0, 90, preAngle);
    63.         Quaternion target = Quaternion.Euler(0, 90, setAngle);
    64.         float dot = Quaternion.Dot(transform.rotation, preTarget);
    65.  
    66.         if (0.9f < dot && hitPre == false)
    67.         {
    68.             hitPre = true;
    69.         }
    70.         else if (hitPre == true)
    71.         {
    72.                 Quaternion temp = Quaternion.Slerp(transform.rotation, target, Time.deltaTime * 5);
    73.                 transform.rotation = temp;          
    74.         }
    75.         else
    76.         {
    77.             Spinning();
    78.         }
    79.     }
    80.  
    81.     private void Spinning()
    82.     {
    83.         transform.Rotate(Vector3.back * Time.deltaTime * speed);
    84.     }
    85. }
    86.  
    Thank you for your help.