Optimizing Lerp and Easing functions

By 04/08/2018 March 20th, 2019 Programming

Premise

Today we’ll talk about the Lerp optimization on structs (which could be Vector3.Lerp, Color.Lerp and so on) and talk about how to optimize easing functions.

We already know the “float” Lerp function, which is the following:

We could encounter problems when we want to apply it to our custom types, such as a Vector3, a Vector2 or a Color.

There are four different ways to implement it, today we’re going to describe all of them and see which has a better performance.

Please, remember that I’m profiling with Unity and I enabled “Deep Profiling” , which takes a lot of resources. These tests are under extreme conditions and will never occur in your game… unless you like to play it on a PotatoMachine5000 and have 500000 objects calling those functions per each frame…which..I mean.. it’s not the best situation.


Lerp Implementation

Let’s use Vector3 as examples; be aware that it’s the same for other struct types (more or less resources needed depending on which one you use).

The different ways to implement “Lerp” with our custom types are the following:


Lerp1 vs Lerp2

Let’s compare the first two types.

You can see the main difference from the profiler, the first type (left) takes more resources because we’re multiplying, adding and subtracting Vector3s. With 75000 Lerps per frame, it takes up almost 70ms of response time.

The second type (right) instead doesn’t need to operate on Vectors and is faster, with 75000 Lerps per frame it takes up almost 50ms.


Lerp3 vs Lerp4

What about  Lerp3 (Unity’s Vector3.Lerp, left) and Lerp4 (Unity’s Vector3.LerpUnclamped, right) ?

As said before, the difference betweenVector3.LerpUnclamped and Vector3.Lerp is that Unity clamps the “t” value in the last one, assuring that it’s included between [0,1]. It simply adds this t = Mathf.Clamp01(t); before the return. You can use Vector3.Lerp if you’re not sure your “t” is included between [0,1], otherwise you can use Vector3.LerpUnclamped and gain even more performance.

Vector3.LerpUnclamped is the winner here, with only 20s of response time. (I must remember to you that I’m “deep profiling” and also calling a “Lerp” 75000 times per frame).


Profiler Tables

Let’s build some tables and see the main differences with also other types:

Vector3
Response time Performance
Lerp1 70ms 28%
Lerp2 50ms 40%
Lerp3 (Or Unity’s Vector3.Lerp) 30ms 66%
Lerp4 (Or Unity’s Vector3.LerpUnclamped) 20ms 100%
Color
Response time Performance
Lerp1 70ms 28%
Lerp2 60ms 33%
Lerp3 (Or Unity’s Color.Lerp) 30ms 66%
Lerp4 (Or Unity’s Color.LerpUnclamped) 20ms 100%
Vector2
Response time Performance
Lerp1 65ms 30%
Lerp2 40ms 50%
Lerp3 (Or Unity’s Vector2.Lerp) 30ms 66%
Lerp4 (Or Unity’s Vector2.LerpUnclamped) 20ms 100%

Lerp Result

You can use Vector3.Lerp and be sure that your percentage value is between [0,1], or use Vector3.LerpUnclamped to maximize the performance.

Don’t worry too much about Lerp or LerpUnclamped if you’re at the beginning of your project! “Premature optimization is the root of all evil“, as every google search tells to you. Aaaand remember that these tests are under extreme conditions, always.


For info, I used this code to debug/profile the Vector3 (and then changed it for each struct type):


Easing Functions

Now that we know which Lerp is the best for us when we’re using structs we have to choose between easing the value directly (giving a linear percentage as a parameter) or interpolate linearly the value based on the eased percentage.

Let’s take “EaseIn” as an example (which is a simple power of two function) and also set the duration and the end value to 1 and the start value to 0.
Let’s also increment the calls per frame to something like 500000!

Both scripts return the same value, but the last one eases only the percentage.

Well, that’s a huge difference! From 70ms to almost nothing, tweening only the percentage.


This is the script that I used to profile:


That’s it for now!

To sum up things, I can say that you can use without worrying Lerp3 (Vector3.Lerp) and Lerp4(Vector3.LerpUnclamped). When easing, you can use a Lerp for the value and provide an “Eased” percentage instead.