How to Use Lerp - Unity Game Development Tutorial

In this Unity game development tutorial we're going to look at the mathematical function Lerp, or linear interpolation.

The Lerp function allows us to linearly interpolate between two values, and is most commonly used for changing values over a period of time. 

While its usage is really common in Unity, it's quite often misunderstood, and can easily be used in the wrong way.

In this tutorial, we'll demonstrate how to use it correctly, and hopefully clear up any confusion.

You can either watch the video version below or continue reading for written instructions.

OK, we're going to start with this scene that has a single cube.

Scene with a single cube

We're going to add a script to this cube to move it from its starting position to a desired destination over a period of time.

We'll select the cube in the Hierarchy. Then we’ll click on Add Component and add a new script. 

Adding the Lerp Movement script

We'll call this script LerpMovement.

Before we update our script, let's have a look at the Unity documentation for Lerp. As we want to change the position, which is a Vector3, we'll look at the Vector3 Lerp method. 

https://docs.unity3d.com/ScriptReference/Vector3.Lerp.html

According to the documentation, we need a start value, an end value and an interpolation value. So if the interpolation value is 0, then the Lerp method will return the start value. If the interpolation value is 1, then the Lerp method will return the end value, and if the interpolation value is 0.5, then it will return the midpoint between the start and end value.

Let's open our script to try this out.

The first thing we'll do is set the end position. We'll create a private Vector3 field and set it to 5 on the X axis and minus 2 on the Y axis.

public class LerpMovement : MonoBehaviour
{
    private Vector3 endPosition = new Vector3(5, -2, 0);
    ...

We'll then create a private field for the start position, and in the Start method, we'll set this to the starting position of the cube.

public class LerpMovement : MonoBehaviour
{
    private Vector3 endPosition = new Vector3(5, -2, 0);
    private Vector3 startPosition;
    
    void Start()
    {
        startPosition = transform.position;    
    }
    ...

We want to move from the start to the end over a period of time, so we'll create a new float field to hold the desired duration, and we'll set this to 3 seconds.

    
    ...
    private float desiredDuration = 3f;
    
    void Start()
    {
        startPosition = transform.position;    
    }
    ...

We also need to create a field to store the amount of time that has passed.

public class LerpMovement : MonoBehaviour
{
    private Vector3 endPosition = new Vector3(5, -2, 0);
    private Vector3 startPosition;
    private float desiredDuration = 3f;
    private float elapsedTime;

    void Start()
    {
        startPosition = transform.position;    
    }
    ...

Now we have everything we need to implement our Lerp.

In the Update method, the first thing we’ll do is increment our elapsed time by Time.deltaTime.

    
    ...
    void Update()
    {
        elapsedTime += Time.deltaTime;        
    }

Next we'll work out the percentage of our desired duration that has elapsed, by dividing elapsed time by the desired duration.

    
    ...
    void Update()
    {
        elapsedTime += Time.deltaTime;
        float percentageComplete = elapsedTime / desiredDuration;
    }

Then we'll update the position using the Lerp method. We'll pass in the original start position, the desired destination, and the percentage of the duration that has elapsed.

    
    ...
    void Update()
    {
        elapsedTime += Time.deltaTime;
        float percentageComplete = elapsedTime / desiredDuration;
    
        transform.position = Vector3.Lerp(startPosition, endPosition, percentageComplete);
    }

This script will move the cube from the start position to the desired destination linearly over 3 seconds.

Let's save the script and switch back to Unity to try it out.

Cube moving using Lerp

The cube moves at a constant speed until it reaches the destination.

Now that we've seen the correct way to use Lerp, let's look at one of the most common ways it's used incorrectly.

Rather than having a static start position, we’ll change the script to use the current position of the cube. We'll also replace the interpolation value with Time.deltaTime.

    
    ...
    void Update()
    {
        elapsedTime += Time.deltaTime;
        float percentageComplete = elapsedTime / desiredDuration;
    
        transform.position = Vector3.Lerp(transform.position, endPosition, Time.deltaTime);
    }

This is a really common usage of Lerp, and you will likely have come across it already in the forums or in tutorials.

On the surface this kind of makes sense. We want to go from the current position, to the target position, over a period of time.

Let's save this and switch back to Unity to see what it does.

Cube moving using incorrect lerp usage

Now the cube starts off moving fast and gradually gets slower and slower as it gets nearer the target destination.

This is because the start position keeps changing, causing the distance between the start and end to decrease each frame. Also, we'll never actually make it all the way to our target destination. As we never pass in the interpolation value of 1, it will just keep getting gradually closer, moving smaller amounts each frame.

The transform position changing gradually

While this isn't the way Lerp was intended to be used, this kind of movement may actually be desirable in some situations.

There is another way to achieve this though. Let's switch back to our script to take a look.

We'll revert our Lerp call back to using the correct parameters.

    
    ...
    void Update()
    {
        elapsedTime += Time.deltaTime;
        float percentageComplete = elapsedTime / desiredDuration;
    
        transform.position = Vector3.Lerp(startPosition, endPosition, percentageComplete);
    }

If we want to create non linear movement, we can do this by modifying the interpolation value. One way we could do this, is by using the SmoothStep function. This will cause it to gradually speed up at the start and slow down at the end. 

    
    ...
    void Update()
    {
        elapsedTime += Time.deltaTime;
        float percentageComplete = elapsedTime / desiredDuration;
    
        transform.position = Vector3.Lerp(startPosition, endPosition, Mathf.SmoothStep(0, 1, percentageComplete));
    }


Let's save the script and try it out.

Cube moving using smooth step

The cube now slows down as it reaches the destination, but it does so in a much more reliable and consistent way.

Another option if you want complete control is to use an animation curve. Let's switch back to our script and add a private AnimationCurve field. We'll mark the field as serializable so that we can set it in the inspector.

    
    ...
    private Vector3 endPosition = new Vector3(5, -2, 0);
    private Vector3 startPosition;
    private float desiredDuration = 3f;
    private float elapsedTime;

    [SerializeField]
    private AnimationCurve curve;
    ...

We'll then use this curve to calculate our interpolation value.

    
    ...
    void Update()
    {
        elapsedTime += Time.deltaTime;
        float percentageComplete = elapsedTime / desiredDuration;
    
        transform.position = Vector3.Lerp(startPosition, endPosition, curve.Evaluate(percentageComplete));
    }


Let's save this and switch back to Unity.

Now, in the Inspector, we can define our curve. First of all, we'll select the linear curve.

Selecting the linear curve

Then we'll press play to try this out.

The cube moving using a linear curve

This gives us our original linear movement.

If we stop the game, we can change the curve to whatever we want. We'll change it to slow down in the middle before speeding up again towards the end.

Curve that slows in the middle

Let’s press play to see what this looks like..

The cube moving using the new curve

Hopefully this tutorial has cleared up how Lerp should be used. The key points to take away are that the start and end should always be fixed, and the interpolation value should go from zero to one over time, and shouldn't just be set to Time.deltaTime.

That covers everything for this tutorial. We hope that you found it useful. Please leave any questions or feedback in the comments below, and don't forget to subscribe to get notified when we publish our next post.

Thanks.


Comments

Popular posts from this blog

Rotating a Character in the Direction of Movement - Unity Game Development Tutorial

Changing the Colour of a Material - Unity Game Development Tutorial

Creating Terrain from Heightmaps - Unity Game Development Tutorial