Slowly rotating towards angle in Unity

Chrisjan Lodewyks picture Chrisjan Lodewyks · Mar 7, 2017 · Viewed 6.9k times · Source

I am using SteamVR and would like to rotate the camera based on the height that a controller has been raised, I have written the script that sends the the height of the controller through to a method on my camera script.

When I do the following, the rotation works:

transform.Rotate(0, 0, 30); // 30 is just to test, we will use the controller height later

But I would like to do this rotation slowly, this must not happen immediately.

I have also tried using Quaternion.Lerp, but it does not seem to be working.

Quaternion.Lerp(this.transform.rotation, new Quaternion(this.transform.rotation.eulerAngles.x, this.transform.rotation.eulerAngles.y, zPosition, 0), Time.deltaTime * 5);

Any suggestions?

Answer

Serlite picture Serlite · Mar 7, 2017

Quaternion.Lerp() should work fine for your needs - however, your usage of it supplies some incorrect parameters to the method, which is why it wasn't working as expected. (Also, you probably shouldn't be constructing a Quaternion using its constructor, there are helper methods to properly convert from Euler angles.)

What you need to do is record the initial starting and ending rotations, and pass them into Quaternion.Lerp() every time you call it. Note that you can't just reference transform.rotation every frame, because it will be changing as the object rotates. For example, adjusting your code to work:

Quaternion startRotation;
Quaternion endRotation;
float rotationProgress = -1;

// Call this to start the rotation
void StartRotating(float zPosition){

    // Here we cache the starting and target rotations
    startRotation = transform.rotation;
    endRotation = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y, zPosition);

    // This starts the rotation, but you can use a boolean flag if it's clearer for you
    rotationProgress = 0;
}

void Update() {
    if (rotationProgress < 1 && rotationProgress >= 0){
        rotationProgress += Time.deltaTime * 5;

        // Here we assign the interpolated rotation to transform.rotation
        // It will range from startRotation (rotationProgress == 0) to endRotation (rotationProgress >= 1)
        transform.rotation = Quaternion.Lerp(startRotation, endRotation, rotationProgress);
    }
}

Hope this helps! Let me know if you have any questions.