Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Quaternion.Lerp() not fully rotating GameObject

Discussion in 'Scripting' started by SamuraiKitty, Nov 8, 2015.

  1. SamuraiKitty

    SamuraiKitty

    Joined:
    Jun 29, 2015
    Posts:
    16
    I'm trying to use Quaternion.Lerp to rotate a GameObject back and forth smoothly. It rotates to -90 degrees (or 270 degrees) and then goes back to 0 degrees (or 360). I get the GameObject to rotate when I press the space bar (toggling two booleans).

    But after a while of toggling those booleans, the Quaternion.Lerp function doesn't rotate to 360, but instead yo 324 degrees, causing the game to not function properly. This only happens when I'm trying to rotate to 360, not 270.

    My code:

    Code (CSharp):
    1.         if (rotateLeft == true)
    2.         {
    3.             Quaternion newDir = Quaternion.AngleAxis(270, Vector3.up);
    4.             transform.GetChild(0).transform.localRotation = Quaternion.Lerp(transform.GetChild(0).transform.rotation, newDir, rotationSpeed * Time.deltaTime);
    5.         }
    6.  
    7.         if (transform.GetChild(0).localEulerAngles.y == 270)
    8.         {
    9.             rotateLeft = false;
    10.  
    11.             print("rotate left false");
    12.         }
    13.  
    14.         if (rotateRight == true)
    15.         {
    16.             Quaternion newDir2 = Quaternion.AngleAxis(360, Vector3.up);
    17.             transform.GetChild(0).transform.localRotation = Quaternion.Lerp(transform.GetChild(0).transform.rotation, newDir2, rotationSpeed * Time.deltaTime);
    18.         }
    19.  
    20.         if (Mathf.RoundToInt(transform.GetChild(0).localEulerAngles.y) == 360)
    21.         {
    22.             rotateRight = false;
    23.  
    24.             print("rotate right false");
    25.         }
    Thanks.
     
  2. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    Alright, I see a couple of problems here.

    You're making direct comparisons to floats, use Mathf.Approximatly instead.
    There are a couple of instances here where you should be caching your components and objects, like the result of transform.GetChild(0), rather than calling it several times.

    Further more, It's unclear with the code you've provided what it is you're trying to accomplish. Why do you need two booleans? Why are you rotating the child object?

    Here's an example of how to rotate between two angles by pressing the space key:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class Rotator : MonoBehaviour {
    4.  
    5.     [SerializeField] bool pointAtA = false;
    6.     [SerializeField,Range(0.5f,10f)] float speed = 6f;
    7.  
    8.     [SerializeField] float angleA = 0f;
    9.     [SerializeField] float angleB = 90f;
    10.  
    11.     Quaternion a;
    12.     Quaternion b;
    13.  
    14.     void Awake()
    15.     {
    16.         a = Quaternion.AngleAxis (angleA, Vector3.forward);
    17.         b = Quaternion.AngleAxis (angleB, Vector3.forward);
    18.     }
    19.  
    20.     void Update()
    21.     {
    22.         if (Input.GetKeyDown (KeyCode.Space))
    23.             pointAtA = !pointAtA;
    24.  
    25.         Quaternion target = pointAtA ? a : b;
    26.         transform.rotation = Quaternion.Slerp (transform.rotation, target, Time.deltaTime * speed);
    27.     }
    28. }
    29.  
    Example scene attached.
     

    Attached Files:

    flonch likes this.
  3. SamuraiKitty

    SamuraiKitty

    Joined:
    Jun 29, 2015
    Posts:
    16
    Thanks for the great answer! My game is a bit like the game ZigZag. But instead of using a ball as the player, I'm using an actual animated character. I need the character to rotate everytime I change direction (either forward or left). I'm rotating the child object instead of the parent object itself because the camera is attached to the parent GameObject but I don't want to rotate that, so instead I put all the body parts into an empty GameObject (which of course is parented to the gameobject with the script attached) and rotate the emtpy gameobject.

    I need two booleans, because I need to find out when I should rotate the gameobject. With my testing, I've found that putting the rotation code directly in the code to get the Space bar input, it only rotates while the space bar is down (Which is an extremely short amount of time, no where near enough to get me to 90 degrees). Then, with the code, I find out when the player has rotated and change the boolean back to false so he can rotate again.

    Here is the code to get the input:
    Code (CSharp):
    1. if (Input.GetKeyDown("space") && dir == Vector3.forward)
    2.                 {
    3.                     score++;
    4.                     scoreText.text = score.ToString();
    5.                     dir = Vector3.left;
    6.                     tempDir = Vector3.left;
    7.  
    8.                     rotateLeft = true;
    9.                 }
    10.                 else if (Input.GetKeyDown("space") && dir == Vector3.left)
    11.                 {
    12.                     score++;
    13.                     scoreText.text = score.ToString();
    14.                     dir = Vector3.forward;
    15.                     tempDir = Vector3.forward;
    16.  
    17.                     rotateRight = true;
    18.                 }
    19.                 else if (Input.GetKeyDown("space") && dir == Vector3.zero)
    20.                 {
    21.                     score++;
    22.                     scoreText.text = score.ToString();
    23.                     dir = Vector3.forward;
    24.                     tempDir = Vector3.forward;
    25.                     GetComponent<Animator>().CrossFade("RunRun", 0f);
    26.  
    27.                     canJump = true;
    28.                 }
    And of course applying the directional movement:
    Code (CSharp):
    1. float amountToMove = speed * Time.deltaTime;
    2.  
    3.         transform.Translate(dir * amountToMove);
    What do you mean by the line "Quaternion target = pointAtA ? a : b;" In your example code?

    Thanks!
     
  4. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    Have you tried out the package that was attached to his post?
     
  5. SamuraiKitty

    SamuraiKitty

    Joined:
    Jun 29, 2015
    Posts:
    16
    Yes I have and I actually got mine to work with his tips. Thanks @BenZed!