Nice fade - lerping everything

A common question I still get asked by Unity users is how to fade or translate something over a specific period of time.

I usually like giving them this coroutine solution for this, as it's callable by any MonoBehavior and easy to understand. You can use this for anything including:

  • Fading between colors 
  • Moving something from one position to another
  • Changing a float or int value over time (something like a light.intensity)
  • Rotating something over time

Here's one that fades a light color from it's current color to red over a time period: 

IEnumerator FadeLightToRed()
{
    Color startColor = light.color;
    Color endColor = Color.red;

    float elapsed = 0f;
    float timeForEffect = 2f;

    while (elapsed < timeForEffect)
    {
        light.color = Color.Lerp(startColor, endColor, elapsed / timeForEffect);
        elapsed += Time.deltaTime;
        yield return null;
    }

    light.color = endColor;
}

How it works

The code is simple, you take a start color from the current light color, you define an end color and then set a time for duration of the effect.

The coroutine then enters a while loop where the elapsed time is incremented every frame until it exceeds the time for effect, at which point it exits and finalizes with exact desired output.

 

Making it more flexible

You can make this much more flexible by moving some of these fields to parameters:

IEnumerator FadeLightColor(Color endColor, float timeForEffect)
{
    Color startColor = light.color;    
    float elapsed = 0f;    

    while (elapsed < timeForEffect)
    {
        light.color = Color.Lerp(startColor, endColor, elapsed / timeForEffect);
        elapsed += Time.deltaTime;
        yield return null;
    }

    light.color = endColor;
}

More control over the fade style

So, the above will always give you a linear fade (Hence the name Lerp, Linear Interpolation) over time, but with the help of Unity's built in animation curves, we can get some very easy interpolation options. First, outside of the coroutine we serialize and AnimationCurve in the monobehavior:

[SerializeField]
AnimationCurve fadeCurve;

This will expose a simple curve editor we can play with!

Now, to have that curve interpreted by our fader, just change the lerp to read:

light.color = Color.Lerp(startColor, endColor, fadeCurve.Evaluate(elapsed / timeForEffect));

That's it, now you can design any kind of curve you like to add personality to your fades!

 

Doing something after the effect

Another thing I sometimes get asked as a followup question is how to do something once the effect is finished, and I often see people run a timer alongside the coroutine. However, if you want, you can add a simple callback to the coroutine instead. Just make sure you include "using System" in your .cs file.

If you don't want to always assign a callback, you can either overload the method or just send it null.

In this case, your final script supporting a parameterless callback with all changes looks like this:

IEnumerator FadeLightColor(Color endColor, float timeForEffect, Action callback)
{
    Color startColor = light.color;        
    float elapsed = 0f;

    while (elapsed < timeForEffect)
    {
        light.color = Color.Lerp(startColor, endColor, elapsed / timeForEffect);
        elapsed += Time.deltaTime;
        yield return null;
    }

    light.color = endColor;
    
    //Check callback wasn't set to null
    //Unity/Mono doesn't support later versions of c# yet which make this easier
    if (callback != null) 
    {
        callback();
    }
}

Further reading

That's it, but I'd encourage you to read up on these functions if you're not familiar with them:

Color.Lerp

Mathf.Lerp

Mathf.LerpUnclamped

Vector3.Lerp

Vector3.LerpUnclamped

Quaternion.Lerp

Quaternion.Slerp

AnimationCurve

If you have any questions, please feel free to ask :)