0
\$\begingroup\$

I have some code to lerp between two colors over a set number of seconds, and the lerp works fine:

private Color lerpingColor;

private IEnumerator LerpColorsOverTime(Color startingColor, Color endingColor, float time)
{
    float step = 0.0f;
    while (step < 1.0f)
    {
        step += Time.deltaTime / time;
        yield return new WaitForSecondsRealtime(Time.deltaTime);
        lerpingColor = Color.Lerp(startingColor, endingColor, step);
    }
}

The problem is, the lerp time takes longer than the time I provide in my parameter. For example, LerpColorsOverTime(Color.white, Color.black, 5.0f); takes over 8 seconds to lerp.

My best guess is that I am being very inefficient in the way I am lerping. I tried accounting for the calculation time, but it does not seem to work. In the particular case shown, it is because calculationTime is always 0, since the code to update the time is never run between my Time.time checks. I tried various approaches, with this being my best:

private Color lerpingColor;

private IEnumerator LerpColorsOverTime(Color startingColor, Color endingColor, float time)
{
    float calculationTime = Time.time;
    float step = 0.0f;
    while (step < 1.0f)
    {
        step += Time.deltaTime / time;
        calculationTime = Time.time - calculationTime;
        yield return new WaitForSecondsRealtime(Time.deltaTime - calculationTime);
        calculationTime = Time.time;
        lerpingColor = Color.Lerp(startingColor, endingColor, step);
    }
}

I also tried other variations of Time.time, such as DateTime.Now.Miliseconds / 1000.0f and Time.realtimeSinceStartup, but they failed as well.

How can I make this code efficient enough to run in the expected time, or make some sort of change with the seemingly same effect?

\$\endgroup\$
2
\$\begingroup\$

Keep in mind that Time.deltaTime is the time between the current frame and the last frame. When calling new WaitForSecondsRealtime(Time.deltaTime) you "guess" the next frame will be in Time.deltaTime seconds. Which may not be true ! And, since Unity is not very precise, you may wait for 2 frames instead of one, resulting in your problem. Yielding null will wait for the next frame.

private IEnumerator LerpColorsOverTime(Color startingColor, Color endingColor, float time)
{
    float inversedTime = 1 / time ; // Compute this value **once**
    for( step = 0.0f; step < 1.0f ; step += Time.deltaTime * inversedTime )
    {
        lerpingColor = Color.Lerp(startingColor, endingColor, step);
        yield return null ;
    }
}
\$\endgroup\$
  • \$\begingroup\$ Definitely an oversight on my part. Thanks! I am using yield return new WaitForEndOfFrame(); now, and it works. \$\endgroup\$ – Evorlor May 11 '17 at 17:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.