Lam Cao's Blog

A Journey in Game Dev

How to use Lerp right.

Lerp, or linear interpolation, is a super useful function we all love. However, I often see devs use it in some weird way. I feel like they never bothered to read the documentation. Well, these devs probably didn’t. Here is an example of how not to use Lerp right.

transform.position = Vector3.Lerp(transform.position, endPoint, Time.deltaTime * speed);

I have seen it in random online tutorials, on Unity Answers and StackOverflow. If you know how it works, then you know the code example above makes no sense! Let’s discuss why.

The Unity’s official documentation explains it well. The Lerp functions basically return the value between two known and fixed endpoints, A and B, given a fraction t, where 0<= t<= 1. This means that if t = 0.5, the value is halfway from A to B; if t = 1, the value = B.

Here are some important lines excerpted from the documentation that shows Lerp is supposed to be done.

// Distance moved = time * speed.
float distCovered = (Time.time - startTime) * speed;
//The length between start and end point.
float journeyLength = Vector3.Distance(startPoint.position, endPoint.position); 
// Fraction of journey completed = current distance divided by total distance.
float fracJourney = distCovered / journeyLength; 

transform.position = Vector3.Lerp(startPoint.position, endPoint.position, fracJourney);

The biggest difference is probably the rate of change (or velocity). The wrong Lerp example doesn’t take into account the length of the “journey”. Assuming Time.deltaTime * speedis not going to change much over time, let’s say the object moves with t = 0.2 (or 20% of the journey) every frame. As the object moves forward, the distance between A and B gets smaller and smaller. 20% of the journey in one frame is not as large as the previous one. As a result, the object appears to move fast at first and slow down toward the end.

When used correctly, approaches 1 at a constant rate and therefore, the object always moves at a constant speed.

In other words, the right code moves the object along the line from A to B while the wrong example moves the start point A toward endpoint B and maintains a relative distance between A and the object.

When done right, the box (below) should move at constant speed and always reach exact target position.

The fact that t = Time.deltaTime * speeddoesn’t change much over time also implies that the object will never get to its target. If t is not equal to 1 then it will never be 1 without a significant change of speed.

The box (above) gets very close to (10,2,0) but never there.

In conclusion, a function should only be used for its intended purpose. When in doubt, know that the documentation is always there. If start point is unknown, or you simply want to use transform.position as the start point, Vector3.MoveTowards is a better choice.

Happy programming!

Leave a Reply

Your email address will not be published. Required fields are marked *