Rotate GameObject over time

Most examples out there including Unity examples from their official website are using Lerp in the wrong way. They didn’t even bother to describe how it works in the API documentation. They just starch it in the Update() function and call it a day.

Mathf.Lerp, Vector3.Lerp, and Quaternion.Slerp work by changing from one position/rotation to another with the t value(last parameter) being passed in.That t value is also know as time.

The min of the t value is 0f and the max is 1f.

I will explain this with Mathf.Lerp to make it easier to understand. The Lerp functions are all the-same for both Mathf.Lerp, Vector and Quaternion.

Remember that Lerp takes two values and returns values between them. If we have a value of 1 and 10 and we do Lerp on them:

 float x = Mathf.Lerp(1f, 10f, 0f); will return 1.
 float x = Mathf.Lerp(1f, 10f, 0.5f); will return 5.5
 float x = Mathf.Lerp(1f, 10f, 1f);  will return 10

As you can see, the t(0) returns the min of the number passed in, t(1) returns the max value passed in and t(0.5) will return mid point between the min and the max value. You are doing it wrong when you pass any t value that is < 0 or > 1. That code in you Update() function is doing just that. Time.time will increase every second and will be > 1 in a second, so you have problems with that.

It recommended to use Lerp in another function/Coroutine instead of the Updated function.

Note:

Using Lerp has a bad side of it when it comes to rotation. Lerp does not know how to rotate Object with the shortest path. So bear that in mind. For example, you have an Object with 0,0,90 position. Lets say you want to move the rotation from that to 0,0,120 Lerp can sometimes rotate left instead of right to reach that new position which means it take longer to reach that distance.

Let’s say we want to make the rotation (0,0,90) from whatever the current rotation is. The code below will change the rotation to 0,0,90 in 3 seconds.

ROTATION OVER TIME:

void Start()
{
    Quaternion rotation2 = Quaternion.Euler(new Vector3(0, 0, 90));
    StartCoroutine(rotateObject(objectToRotate, rotation2, 3f));
}

bool rotating = false;
public GameObject objectToRotate;
IEnumerator rotateObject(GameObject gameObjectToMove, Quaternion newRot, float duration)
{
    if (rotating)
    {
        yield break;
    }
    rotating = true;

    Quaternion currentRot = gameObjectToMove.transform.rotation;

    float counter = 0;
    while (counter < duration)
    {
        counter += Time.deltaTime;
        gameObjectToMove.transform.rotation = Quaternion.Lerp(currentRot, newRot, counter / duration);
        yield return null;
    }
    rotating = false;
}

INCREMENTAL ANGULAR ROTATION OVER TIME:

And to just rotate the Object to 90 in z axis, the code below is a great example of that. Please understand there is a difference between moving Object to new rotational point and just rotating it.

void Start()
{
    StartCoroutine(rotateObject(objectToRotate, new Vector3(0, 0, 90), 3f));
}

bool rotating = false;
public GameObject objectToRotate;

IEnumerator rotateObject(GameObject gameObjectToMove, Vector3 eulerAngles, float duration)
{
    if (rotating)
    {
        yield break;
    }
    rotating = true;

    Vector3 newRot = gameObjectToMove.transform.eulerAngles + eulerAngles;

    Vector3 currentRot = gameObjectToMove.transform.eulerAngles;

    float counter = 0;
    while (counter < duration)
    {
        counter += Time.deltaTime;
        gameObjectToMove.transform.eulerAngles = Vector3.Lerp(currentRot, newRot, counter / duration);
        yield return null;
    }
    rotating = false;
}

All my examples are based on frame-rate of the device. You can use real-time by replacing Time.deltaTime with Time.delta but more calculation is required.

Leave a Comment