Programmer
Programmer

Reputation: 39

Smooth LookRotation in Coroutine

I am rotating my camera to lookat a target object using Quaternion. I am using Quaternion.LookRotation and Quaternion.Slerp to make the camera rotate smoothly inside coroutine. Unfortunately the camera jitters a lot when rotating. How do I make the rotation smooth with my current code?

Quaternion targetRotation;
public Transform lookAtObject;

IEnumerator RotateTowardsTarget () {

        var duration = 2.0f;
        for (float t = 0.0f; t < duration; t += Time.deltaTime) {
            targetRotation = Quaternion.LookRotation (lookAtObject.position - transform.position);
            transform.rotation = Quaternion.Slerp (transform.rotation, targetRotation, t / duration);
            yield return null;
        }
    }

Upvotes: 0

Views: 999

Answers (2)

derHugo
derHugo

Reputation: 90872

You currently always start the lerp at the current rotation towards the target.

In your usecase what you rather want to do is store the initial rotation and rather interpolate between the initial and target rotation like

IEnumerator RotateTowardsTarget () 
{
    var duration = 2.0f;

    // store the initial and target rotation once
    var startRotation = transform.rotation;
    var targetRotation = Quaternion.LookRotation (lookAtObject.position - transform.position);

    for (var timePassed = 0.0f; timePassed < duration; timePassed += Time.deltaTime) 
    {
        var factor = timePassed / duration;
        // optionally add ease-in and -out
        //factor = Mathf.SmoothStep(0, 1, factor);

        transform.rotation = Quaternion.Slerp (startRotation, targetRotation, factor);
        yield return null;
    }

    // just to be sure to end up with clean values
    transform.rotation = targetRotation;
}

This will make the camera go from the current to the new rotation linear within 2 seconds

Upvotes: -1

Moazan Amjad
Moazan Amjad

Reputation: 57

Slerp takes third parameter as progress not as actual time you can do this

       void Update () {
                
                    StartCoroutine(RotateOverTime(transform.rotation, 
                    lookAtObject.rotation, 1f / speed));
            }
         
            IEnumerator RotateOverTime (Quaternion originalRotation, Quaternion 
            finalRotation, float duration) {
                if (duration > 0f) {
                    float startTime = Time.time;
                    float endTime = startTime + duration;
                    transform.rotation = originalRotation;
                    yield return null;
                    while (Time.time < endTime) {
                        float progress = (Time.time - startTime) / duration;
                        // progress will equal 0 at startTime, 1 at endTime.
                        transform.rotation = Quaternion.Slerp (originalRotation, 
                        finalRotation, progress);
                        yield return null;
                    }
                }
                transform.rotation = finalRotation;
            }

You can now send in duration as seconds

Upvotes: 0

Related Questions