Lerp in Unity

The right way to Lerp in Unity (with examples)

In Unity by John8 Comments

Very often in Unity, you may want to animate a button, move an object to a new position, smoothly fade audio or graphics or, perhaps, change the colour of something gradually over time.

And for those tasks, as well as many others, you’re probably going to need to use Lerp, one way or another.

What is Lerp in Unity?

Lerp, or Linear Interpolation, is a mathematical function in Unity that returns a value between two others at a point on a linear scale.

Most commonly it’s used for moving or changing values over a period of time.

It’s an incredibly common feature of Unity, and development in general,

However…

Surprisingly, it’s often misunderstood and can easily be used the wrong way, especially if you’re just getting started in Unity.

And, while this isn’t always a problem, it can lead to some unexpected results.

For example, it might mean that you can’t recreate the effect you want, or the Lerped animation may appear broken, or buggy or may not work at all.

Or, if you’re anything like me, you might occasionally forget how to use Lerp and need to look it up again every time you need to use it.

Which could be a lot.

But don’t worry, because that’s exactly what you’ll learn on this page.

In this post, I explain the basics of Lerp in Unity, when to use it and how to easily write a Lerp function (as well as how to add special effects, such as easing) with examples that you can use in your project.

What you’ll find on this page:

Let’s start with the basic method…

Advertisement

How to use Lerp

The first thing that you need to know about Lerp, that will make it much, much easier to use, is that the basic Lerp calculation is actually very simple.

It’s how it’s used that often becomes complicated and confusing.

Here’s how Lerp works…

The Lerp calculation returns a value from a known range, which is specified using a minimum and maximum value (a & b). For example, a range of 0-100.

The value that’s returned is defined by a third value, the interpolation point (t) which returns a point on the scale between a and b.

The interpolation point that’s passed in is a float value between 0 and 1. Essentially, acting as a percentage between a and b.

For example…

An interpolation point of 0 (0%) would return the minimum value (in this case also 0) while an interpolation point of 0.5 (50%) would return a value halfway between the minimum and maximum value (in this case, 50).

Here’s what it looks like in scripting:

lerpValue = Mathf.Lerp(minValue, maxValue, interpolationPoint);

And here are some examples:

float a = 0;
float b = 50;
float t = 0.5f;

lerpValue = Mathf.Lerp(a, b, t);

// Returns 25
float a = 10;
float b = 50;
float t = 1;

lerpValue = Mathf.Lerp(a, b, t);

// Returns 50

You get the idea.

In this example, Lerp is being used to return a float, but it’s also possible to Lerp other values, such as colours and Vector3 values (more on that later).

It works in exactly the same way, retrieving a mid-point value from a range using a percentage interpolation point.

And that’s all there is to it.

That’s Lerp!

But how is that useful?

When would you use it?

And where does all the confusion come from?

Advertisement

The right way to use Lerp

Lerp example in Unity

Lerp can be used to create simple movement and animations.

A common use for Lerp is to produce an effect over a fixed period of time.

For example, to animate a button, fade the screen to black or move an object to a new position in a fixed amount of time.

This is done by increasing the interpolation point value from 0 to 1 over that duration.

Here’s how to do it:

  • Create a timer, incrementing it every frame of the Lerp.
  • Divide the time elapsed by the total duration of the Lerp.
  • Pass in that value as the interpolation point (t).

For example, the script below will increment a value from 0 to 10 in 3 seconds time:

float timeElapsed;
float lerpDuration = 3;

float startValue=0;
float endValue=10;
float valueToLerp;

void Update()
{
  if (timeElapsed < lerpDuration)
  {
    valueToLerp = Mathf.Lerp(startValue, endValue, timeElapsed / lerpDuration);
    timeElapsed += Time.deltaTime;
  }
}

Simple right?

If you try this method, however, you’ll notice that the value doesn’t quite reach ten, often ending on a very close, but not exact, value. Such as 9.998 for example.

This is because the value that’s being used to measure if the Lerp is complete is time, not the actual value that’s being Lerped.

To fix this, ‘snap’ the value that’s being Lerped to the final target value after the Lerp is complete.

Like this:

void Lerp()
  {
    if (timeElapsed < lerpDuration)
    {
      valueToLerp = Mathf.Lerp(startValue, endValue, timeElapsed / lerpDuration);
      timeElapsed += Time.deltaTime;
    }
    else 
    {
      valueToLerp = endValue;
    }
  }

Finally, because Lerp functions are often used to carry out an action over multiple frames, it can be helpful to place them in a Coroutine.

This makes them easier to write, easier to manage and, once they’re finished, they stop themselves.

Here’s the same example, written in a Coroutine:

float lerpDuration = 3; 
float startValue = 0; 
float endValue = 10; 
float valueToLerp;

void Start()
    {
        StartCoroutine(Lerp());
    }

IEnumerator Lerp()
    {
        float timeElapsed = 0;

        while (timeElapsed < lerpDuration)
        {
            valueToLerp = Mathf.Lerp(startValue, endValue, timeElapsed / lerpDuration);
            timeElapsed += Time.deltaTime;

            yield return null;
        }

        valueToLerp = endValue;
    }

When used in this way, Lerp is a simple, helpful method for creating animations and movement

However,

Despite being simple, there are a surprising number of examples of Lerp being used the wrong way.

Or, at least, not in the way that Lerp is supposed to be used.

For example…

Advertisement

Lerp slowing down at the end (and how to stop it)

The wrong way to Lerp

This slowing effect is actually a result of using Lerp the wrong way.

You may have seen this method of using Lerp before:

transform.position = Vector3.Lerp(transform.position, target.position, Time.deltaTime);

Although it’s used often, it’s not how Lerp is supposed to work.

The clue is in the name, Linear Interpolation.

Linear!

And, while you can argue that the easing effect of the object slowing down is desirable, it has issues.

One of which is that the object will, most probably, never reach the target. It will just get closer and closer in ever-decreasing amounts.

However…

This kind of movement can be very useful.

Especially when you want to ease an object constantly, and smoothly, towards another object every frame (i.e. not over a fixed time scale). For example, when creating a camera follow script, such as this one by Brackeys (YouTube).

But,

There is a better way to do it.

While the Lerp method may work for you, Smooth Damp is specifically designed for just this kind of task.

It works in a similar way except that it will stop once it reaches the target (or at least, close enough) and it won’t overshoot.

Smooth Damp also works more smoothly, with some users having reported jerky movement when using the Lerp method which, although very slight, I also found to be true during my research for this article.

These methods create a constant, dampened movement towards another value.

But what if you want to Lerp over a fixed duration and you want to apply easing to the movement?

Advertisement

How to ease Lerp in and out (the right way)

When using Lerp over time, the change is even and linear.

This happens because the interpolation point value (t) that’s passed in is calculated by dividing time elapsed by the total duration and, every frame, increasing time elapsed by a linear amount (i.e. using Time.deltaTime).

But what if you don’t want linear movement?

What if you want to ease the start or end of the Lerp?

You can do this by modifying the interpolation point value after it’s calculated but before passing it into the Lerp function.

All you need is a formula, and which one you use depends on what kind of curve you want.

For example, the calculation below creates a Smooth Step Lerp movement:

float t = time / duration;
t = t * t * (3f - 2f * t);

transform.position = Vector3(startPosition, endPosition, t);

This Lerp starts slow, is linear in the middle and then slows towards the end.

Here’s how it looks plotted over a chart:

Smooth Step Lerp

And here’s what it looks like when applied to a Lerp movement script.

Notice the block speeding up as it starts and slowing down as it reaches the target:

Lerp with easing example in Unity

Modifying the interpolation point value (t) eases the start and end of this movement.

Different easing effects can be achieved with different calculations.

For more curve formulas, try chicounity3d.wordpress.com or this article at febucci.com.

Alternatively, tweening assets, such as DOTween Pro, feature built-in easing options (more on DOTween later).

Advertisement

Using Lerp by speed (instead of time)

Another commonly promoted use of Lerp is to change a value at a fixed rate.

Typically this involves incrementing a speed value that’s multiplied by Time.delta Time and then passing that in as the interpolation point.

Usually, it looks something like this:

void Update()
    {
        float valueToLerp = Mathf.Lerp(a, b, t);
        t += 0.5f * Time.deltaTime;
    }

Surprisingly, this is used in the official Unity documentation on Lerp, where the example shown uses an interpolation value of 0.5f + Time.deltaTime.

As with the slow down method, this is not how Lerp is supposed to work.

However, unlike before, there’s no obvious reason to use this method.

The calculation, in this case, does not perform movement over a set period of time working, instead, at a set speed.

And while you could argue that’s helpful, there are easier options for doing exactly that.

For example, to increase any value by one unit per second, simply increment it by one multiplied by delta time each frame.

There’s no need to use Lerp.

Like this:

if(value < targetValue)
{
    value += 1 * Time.deltaTime;
}

It’s also possible to move an object by a fixed speed using Move Towards, or rotate it with Rotate Towards.

So I’m not sure if this method of using Lerp to achieve a constant speed has a useful purpose.

And while I’m an advocate of using less conventional methods if they are easier to work with, or if they achieve a specific result when nothing else will do, using Lerp in this way seems to be more difficult.

But maybe I’m wrong…

Let me know in the comments if you’ve got a great reason for using Lerp like this.

When I use Lerp, the movement stutters and jerks. Why isn’t it smooth?

Sometimes when using Lerp, for example, to move an object, you may notice that the movement is not completely smooth, that it jerks around or appears bumpy.

For example the travel of the object stutters and jumps along its path, even though the movement is linear.

If this is happening to you, don’t worry.

While there are real issues that can cause this, the most likely reason is simply that you’re viewing it in the editor.

And, once you build the project, you’ll notice that the movement in the finished application is buttery smooth.

No need to worry.

Advertisement

Examples of using Lerp

Lerp can be used to smoothly change all kinds of different values, such as floats, Vector3 values, Quaternions and colours.

Some values require slightly different methods, however, most of the examples on this page follow a simple layout.

Blank Lerp template:

public float targetValue;

void Start()
{
  StartCoroutine(LerpFunction(targetValue, 5));
}

IEnumerator LerpFunction(float endValue, float duration)
{
  float time = 0;
  float startValue = valueToChange;

  while (time < duration)
  {
    valueToChange = Mathf.Lerp(startValue, endValue, time / duration);
    time += Time.deltaTime;
    yield return null;
  }
  valueToChange = endValue;
}

This blank example will Lerp a float. Simply replace valueToChange with the value you want to Lerp.

But what about values other than floats.

What does it look like to Lerp those?

How to Lerp a Vector 3

Lerp Vector 3 Unity

In this example, pass in a Vector3 location for the position to move to, ideal for moving an object to a new position over a fixed duration.

This also works with a GameObject, just use GameObject.transform.position whenever you want to access the Vector3 position value of an object.

Here’s what Lerping a Vector 3 looks like in scripting:

public class LerpToPosition : MonoBehaviour
{
    public Vector3 positionToMoveTo;

    void Start()
    {
        StartCoroutine(LerpPosition(positionToMoveTo, 5));
    }

    IEnumerator LerpPosition(Vector3 targetPosition, float duration)
    {
        float time = 0;
        Vector3 startPosition = transform.position;

        while (time < duration)
        {
            transform.position = Vector3.Lerp(startPosition, targetPosition, time / duration);
            time += Time.deltaTime;
            yield return null;
        }
        transform.position = targetPosition;
    }
}

Alternatively, try Move Towards to move to a set point at a fixed speed.

How to Lerp a Vector 2

The same method works for Lerping movement in 2D games as well, simply replace Vector3 with Vector2 and the same Lerp calculation will work.

Like this:

public class Lerp2D : MonoBehaviour
{
    public Vector2 positionToMoveTo;

    void Start()
    {
        StartCoroutine(LerpPosition(positionToMoveTo, 5));
    }

    IEnumerator LerpPosition(Vector2 targetPosition, float duration)
    {
        float time = 0;
        Vector2 startPosition = transform.position;

        while (time < duration)
        {
            transform.position = Vector2.Lerp(startPosition, targetPosition, time / duration);
            time += Time.deltaTime;
            yield return null;
        }
        transform.position = targetPosition;
    }
}

Advertisement

How to Lerp Rotation

Lerp Rotation in Unity

Lerping Rotation is useful for rotating an object to an angle over a period of time.

In this example, the target rotation is passed in as a user-friendly Euler Angle (the Vector 3 angle you’re used to seeing in the Unity inspector).

However, it ‘s possible to deal with native Quaternions instead. Simply use a Transform reference as the target variable and pass in its direct rotation value.

In scripting, Lerping rotation with looks like this:

public Vector3 targetRotation;

    void Start()
    {
        StartCoroutine(LerpFunction(Quaternion.Euler(targetRotation), 5));
    }

    IEnumerator LerpFunction(Quaternion endValue, float duration)
    {
        float time = 0;
        Quaternion startValue = transform.rotation;

        while (time < duration)
        {
            transform.rotation = Quaternion.Lerp(startValue, endValue, time / duration);
            time += Time.deltaTime;
            yield return null;
        }
        transform.rotation = endValue;
    }

How to Lerp scale

Lerp Scale in Unity

This one works a little differently as it uses a modifier value to alter the scale.

This makes it easier to change the entire scale of an object by a single float value, without needing to use a Vector 3.

However, it also means that the current scale of the object is controlled by an arbitrary variable that is not natively accessible (e.g. like position or rotation are).

This means that to change the scale again, (for example, to scale up to twice the size only to then scale back down to the original size later) the scale modifier needs to be stored and accessible outside of the Lerp function.

This way, the relative scale is known and can be referenced if the function is used again.

Here’s what it looks like in scripting:

public float targetScale;
public float timeToLerp = 0.25f;
float scaleModifier = 1;

void Start()
  {
    StartCoroutine(LerpFunction(targetScale, timeToLerp));
  }

  IEnumerator LerpFunction(float endValue, float duration)
  {
    float time = 0;
    float startValue = scaleModifier;
    Vector3 startScale = transform.localScale;

    while (time < duration)
    {
      scaleModifier = Mathf.Lerp(startValue, endValue, time / duration);
      transform.localScale = startScale * scaleModifier;
      time += Time.deltaTime;
      yield return null;
    }
    transform.localScale = startScale * targetScale;
    scaleModifier = targetScale;
  }

Advertisement

How to Lerp a Material’s Colour

Lerp Colour in Unity

Did you know you can Lerp colours too?

Well, you can! With Color.Lerp

You can set a target colour in the inspector or use RGBA values to control the colour and the alpha from scripting.

In this example, I’m setting a material’s colour to green:

public class LerpMaterialColour : MonoBehaviour
{
    public Color targetColor = new Color(0, 1, 0, 1); 
    public Material materialToChange;

    void Start()
    {
        materialToChange = gameObject.GetComponent<Renderer>().material;
        StartCoroutine(LerpFunction(targetColor, 5));
    }

    IEnumerator LerpFunction(Color endValue, float duration)
    {
        float time = 0;
        Color startValue = materialToChange.color;

        while (time < duration)
        {
            materialToChange.color = Color.Lerp(startValue, endValue, time / duration);
            time += Time.deltaTime;
            yield return null;
        }
        materialToChange.color = endValue;
    }
}

Fade Camera to black using Lerp

Fade Camera to Black Unity

It’s possible to fade any Canvas element with the Set Alpha method of the Canvas Renderer component.

When used with a full-screen black image that is drawn above all the other elements, this can be used to fade the Scene in or out:

using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;

public class FadeToBlack : MonoBehaviour
{
    public float targetValue = 0;
    CanvasRenderer elementToFade;

    void Start()
    {
        elementToFade = gameObject.GetComponent<CanvasRenderer>();
        StartCoroutine(LerpFunction(targetValue, 3));
    }

    IEnumerator LerpFunction(float endValue, float duration)
    {
        float time = 0;
        float startValue = elementToFade.GetAlpha();

        while (time < duration)
        {
            elementToFade.SetAlpha(Mathf.Lerp(startValue, endValue, time / duration));

            time += Time.deltaTime;
            yield return null;
        }
        elementToFade.SetAlpha(endValue);
    }
}

How to fade out Text using Lerp

The Canvas Renderer method also works for other Canvas elements as well, such as Text.

Alternatively, the same effect can be achieved by Lerping the colour value of a Text object directly.

Like this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;

public class LerpColour : MonoBehaviour
{
    // Fades the text out
    public Color targetColor = new Color(0,0,0,0);
    Text textToFade;

    void Start()
    {
        textToFade = gameObject.GetComponent<Text>();
        StartCoroutine(LerpFunction(targetColor, 5));
    }

    IEnumerator LerpFunction(Color endValue, float duration)
    {
        float time = 0;
        Color startValue = textToFade.color;

        while (time < duration)
        {
            textToFade.color = Color.Lerp(startValue, endValue, time / duration);
            time += Time.deltaTime;
            yield return null;
        }
        textToFade.color = endValue;
    }
}

Note that these examples use UI elements, so they require the using UnityEngine.UI namespace.

Fade out a sprite using Lerp

The same technique can be applied to changing the colour, and transparency of Sprites.

Typically the colour of a sprite is white, meaning that the sprite isn’t tinted a different colour.

So, to fade out a sprite, you’ll usually only have to store the existing colour if you’ve changed it, while Lerping the alpha value to 0 (transparent) or 255 (opaque) as you need.

Like this:

// Fades the sprite out
public Color targetColor = new Color(1, 1, 1, 0);
SpriteRenderer spriteToFade;

    void Start()
    {
        spriteToFade = gameObject.GetComponent<SpriteRenderer>();
        StartCoroutine(LerpFunction(targetColor, 5));
    }

    IEnumerator LerpFunction(Color endValue, float duration)
    {
        float time = 0;
        Color startValue = spriteToFade.color;

        while (time < duration)
        {
            spriteToFade.color = Color.Lerp(startValue, endValue, time / duration);
            time += Time.deltaTime;
            yield return null;
        }
        spriteToFade.color = endValue;
    }

Fade out an Audio Source using Lerp

Fading an Audio Source over time, from its current value to a new value, uses a similar method as the other Lerp examples.

Setting the current value makes Lerp functions much easier to reuse, as you don’t have to worry about the start point, only the target value.

Here’s what it looks like to Lerp an Audio Source’s volume:

public float targetValue=0;
public AudioSource audioSource;

void Start()
  {
    audioSource = GetComponent<AudioSource>();
    StartCoroutine(LerpFunction(targetValue, 5));
  }

  IEnumerator LerpFunction(float endValue, float duration)
  {
    float time = 0;
    float startValue = audioSource.volume;

    while (time < duration)
    {
      audioSource.volume = Mathf.Lerp(startValue, endValue, time / duration);
      time += Time.deltaTime;
      yield return null;
    }
    audioSource.volume = endValue;
  }

Audio Sources are easy to fade as their 0-1 volume scale creates an even linear fade.

However, if you’ve followed any of my other posts or videos, you may already know that the same is not true when fading an Audio Mixer Group (including when making a volume control slider) which takes a bit of extra work to do properly.

Using an asset to Lerp (e.g. DOTween Pro)

Hopefully I’ve shown that using Lerp to animate and move objects can be easy.

But, it can be even easier than that.

There are a number of Unity assets available that provide code-free alternatives to writing your own Lerp scripts.

DOTween Pro Unity Icon

DOTween Pro, for example, which is probably the most popular and fully-featured, provides a simple, inspector-based component to easily add animation and movement to objects.

Essentially, it does everything you’ve read about in this post (plus a whole lot more) from a component in the inspector.

But is it worth it? Or is it easier to write your own scripts?

I wanted to find out.

So, after writing this post, I bought DOTween Pro from the Unity Asset Store, costing $15 , to see if it was any faster, or easier, to use an asset instead of writing my own code.

Keep in mind that, while researching for this article, I’ve been writing Lerp scripts for days.

As someone who used to forget how to use Lerp and had to look it up every time, I’ll probably never be more familiar with it than I am right now, writing this.

However,

Despite my unfair advantage…

I still got much faster results when using DOTween Pro.

DOTween Unity Asset screenshot

DOTween makes Lerp-style animations easier and much, much faster.

Getting the object moving, fading, or rotating was extremely fast, I could preview it from the editor, and it was easy to get the results I wanted without ever opening a script.

Beyond this, there are also a huge number of easing options, path animation and options to connect with other scripts, objects or UI events.

So would I use it?

For a simple, one-off animation, I’d probably just write a simple script.

Or, more likely, I’d copy one of the examples above and change the values.

However,

For anything larger than a small project, if I’m likely to be using Lerp over and over again, and especially if I want to create complex, chained animation and movements, I’d be much better off using DOTween Pro.

Even if I only used it to create animations that I could write manually, the amount of time I’m likely to save will easily outweigh the cost.

And that’s ignoring the other, more advanced features, which would be extremely difficult for me to recreate manually.

So, I’ll definitely be using it again and I definitely recommend it.

Now I want to hear from you

Are you using Lerp to create animation or movement in your project?

How are you using it? And have you been using any unconventional methods to get the effect you want?

Or maybe you’ve got a great tip for using Lerp that others would love to know?

Whatever it is, let me know by leaving a comment.

by John Leonard French

Game audio professional and a keen amateur developer.

Get Helpful Game Development Tips, Straight to Your inbox

Get access to exclusive tips & tricks and master game development basics the easy way, with deep-dive tutorials and guides.

Popular Posts

Comments

  1. great efforts man and very helpful and clear examples, thank you and keep it up ..

  2. 2 days ago i made some UI element animations and i was like should i use DOTween and i was like naaaah… it’s prolly faster if i write it myself. But luckily you did the reserach for me for complex ones.
    Anyway nice and clean programming you do despite the fact that your are an Audio engineer, keep up the goodwork!

  3. Great article. What I found to be an easy way of changing the curve of the lerp is to use an AnimationCurve. For the t-parameter I’d use: “AnimationCurve.Evaluate(time/duration)”
    It’s way easier than writing curve functions ^^

Leave a Comment