Home > Enterprise >  Smooth LookRotation in Coroutine
Smooth LookRotation in Coroutine

Time:11-22

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;
        }
    }

CodePudding user response:

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.0;

    // 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

CodePudding user response:

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

  • Related