0
\$\begingroup\$

In my current script responsible for camera movement, I use Mathf.Lerp to smoothly move the camera to the desired position (with WASD movement, panning with MMB, and zooming with the scrollwheel).

However, due to the nature of the Lerp method, I have performance concerns. Does it ever stop calculating the distance and slightly moving the camera towards the location, or do I have to have an if statement that checks if a distance is < 0.0005f, then stop lerping? If so, which is more performant / better practice?

As a bonus question, I've seen there are other smoothing functions such as MoveTowards, Slerp, SmoothDamp... is there any benefit to using any of those over lerp? My main priority is the camera movement being as performant as possible, and I don't understand how these functions work behind the scenes, despite doing much research.

The entire code to my CameraController is here (the lerping is done in LateUpdate): https://pastebin.com/URZhq3MA

\$\endgroup\$
3
  • 2
    \$\begingroup\$ Sounds like you're using an exponential ease-out lerp. That's not the only way to use lerp. It is not a performance limitation - lerp is just a couple multiplications and adds, so it does not add a significant performance cost. The same goes for the alternatives you listed - profile them and you'll see that moving one object with any of these functions is effectively free. \$\endgroup\$
    – DMGregory
    Mar 9 at 16:06
  • \$\begingroup\$ So for my case, I can leave it as is and not worry that it never quite reaches the target? If I did check for distance, then I'd have to call an if statement in each Update which would probably end up being even more expensive, right? \$\endgroup\$ Mar 9 at 16:13
  • 1
    \$\begingroup\$ I always recommend measuring consequences. Does anything noticeably bad happen when you use this code as-is? If so, ask for a way to solve that bad outcome. If not, then this is not the thing you need to worry about, and there are probably other parts of your game that could benefit from your attention. (But do fix your delta time correction as described in the link above - your current math is wrong) \$\endgroup\$
    – DMGregory
    Mar 9 at 16:26
2
\$\begingroup\$

All of these functions are simply math functions. When you call them, they do math on the numbers you give them, and give you back a number. Nothing more mysterious than that.

Does it ever stop calculating the distance and slightly moving the camera towards the location

Lerp never calculates a distance and it never moves your camera.

Your code might do those things, and your code calls Lerp somewhere in that process. Every time your code calls Lerp, it does its work, which is very simple:

public static Vector3 Lerp(Vector3 a, Vector3 b, float t)
{
    t = Mathf.Clamp01(t);
    return new Vector3(
        a.x + (b.x - a.x) * t,
        a.y + (b.y - a.y) * t,
        a.z + (b.z - a.z) * t
    );
}

You can see there's no distance calculation or branching logic to decide whether it should do anything hiding in there. It's just six addition/subtractions and three multiplications. You'd have to run this millions of times in a frame to measure the cost, it's so cheap.

For one-off scripts like your camera controller, this simply is not something to worry about. You're going to be taking a cache miss when you fetch the camera control script and data from memory anyway, which is already hundreds of times more expensive than this little bit of math. (And your processor might be twiddling its thumbs waiting for the next object it needs to arrive in cache, so you might be able to do a significant amount of work here "for free" while you're waiting anyway)

MoveTowards and SmoothDamp are a little more complicated (you can see their implementations too at the link above), and Slerp involves some trigonometry, but they all fall into that "effectively free when you're using them in a one-off script" category.

New coders often think that the way you make a program fast is to make little micro-optimizations to every line, believing that any excess cost adds up / that any minor saving should add up to a significant speed-up, if you do enough of them. Unfortunately that's not how modern computers work. You'll typically be bottlenecked on a few rate-determining steps, like the time it takes to render the frame. Making other parts of your code faster doesn't make the game as a whole run any faster if it's still waiting on those bottlenecks.

So: always profile first. Measure what parts of your game are actually making it slow, then investigate ways to solve those.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.