Quaternion.Lerp() not fully rotating GameObject

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:

        if (rotateLeft == true)
        {
            Quaternion newDir = Quaternion.AngleAxis(270, Vector3.up);
            transform.GetChild(0).transform.localRotation = Quaternion.Lerp(transform.GetChild(0).transform.rotation, newDir, rotationSpeed * Time.deltaTime);
        }

        if (transform.GetChild(0).localEulerAngles.y == 270)
        {
            rotateLeft = false;

            print("rotate left false");
        }

        if (rotateRight == true)
        {
            Quaternion newDir2 = Quaternion.AngleAxis(360, Vector3.up);
            transform.GetChild(0).transform.localRotation = Quaternion.Lerp(transform.GetChild(0).transform.rotation, newDir2, rotationSpeed * Time.deltaTime);
        }

        if (Mathf.RoundToInt(transform.GetChild(0).localEulerAngles.y) == 360)
        {
            rotateRight = false;

            print("rotate right false");
        }

Thanks.

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:

using UnityEngine;

public class Rotator : MonoBehaviour {

    [SerializeField] bool pointAtA = false;
    [SerializeField,Range(0.5f,10f)] float speed = 6f;

    [SerializeField] float angleA = 0f;
    [SerializeField] float angleB = 90f;

    Quaternion a;
    Quaternion b;

    void Awake()
    {
        a = Quaternion.AngleAxis (angleA, Vector3.forward);
        b = Quaternion.AngleAxis (angleB, Vector3.forward);
    }

    void Update()
    {
        if (Input.GetKeyDown (KeyCode.Space))
            pointAtA = !pointAtA;

        Quaternion target = pointAtA ? a : b;
        transform.rotation = Quaternion.Slerp (transform.rotation, target, Time.deltaTime * speed);
    }
}

Example scene attached.

2373114–161279–Rotator.unitypackage (5.57 KB)

1 Like

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:

if (Input.GetKeyDown("space") && dir == Vector3.forward)
                {
                    score++;
                    scoreText.text = score.ToString();
                    dir = Vector3.left;
                    tempDir = Vector3.left;

                    rotateLeft = true;
                }
                else if (Input.GetKeyDown("space") && dir == Vector3.left)
                {
                    score++;
                    scoreText.text = score.ToString();
                    dir = Vector3.forward;
                    tempDir = Vector3.forward;

                    rotateRight = true;
                }
                else if (Input.GetKeyDown("space") && dir == Vector3.zero)
                {
                    score++;
                    scoreText.text = score.ToString();
                    dir = Vector3.forward;
                    tempDir = Vector3.forward;
                    GetComponent<Animator>().CrossFade("RunRun", 0f);

                    canJump = true;
                }

And of course applying the directional movement:

float amountToMove = speed * Time.deltaTime;

        transform.Translate(dir * amountToMove);

What do you mean by the line “Quaternion target = pointAtA ? a : b;” In your example code?

Thanks!

Have you tried out the package that was attached to his post?

Yes I have and I actually got mine to work with his tips. Thanks @BenZed !