Why does Mathf.Lerp never quite reach its target value?

I’m trying to implement a vehicle throttle by lerping the throttle setting between its current value and a desired value, modified by acceleration every update:

public float currentThrottle; 
public float desiredThrottle;
public float acceleration = 0.5f;

void AdjustThrottle()
{
    if (currentThrottle != desiredThrottle)
    {
        currentThrottle = Mathf.Lerp(currentThrottle, desiredThrottle, acceleration * Time.deltaTime);
    }
    //Lerp currentThrottle towards DesiredThrottle
}

This results in a pleasing and fairly convincing acceleration until currentThrottle approaches desiredThrottle, at which point acceleration slows to a crawl and never manages to quite hit its target. Should I be using something other than delta time to actually moderate my lerp?

This is a mathematically incorrect use of Lerp, and will result in somewhat different results on different speed CPUs. The correct way to use Lerp is to set the third parameter (t) from 0.0 to 1.0 directly, not additively with Time.deltaTime. In this case you’re probably better off using MoveTowards.

Where are you updating your AdjustThrottle() ?
You may put it inside Update(), or use InvokeRepeating, whatever you want.

It does, exactly, return the final value when you supply 1.0 as the third parameter. Here’s a good explanation of how to use lerp correctly: Using Vector3.Lerp() correctly in Unity — One Man's Trash is Another Man's Blog

Mathematically, this is why:

When you lerp between the current value and a target value each frame, what happens is that the currentValue moves closer to the targetValue by a percentage of the distance between the two.

If your ‘acceleration’ parameter is set to one, and your framerate is one frame per second, then Time.deltaTime will be 1 second the first time that Mathf.Lerp is called, and currentSpeed will be set to targetSpeed exactly.

If your frameRate goes up to two frames per second, then Mathf.deltaTime will be 0.5 the first time that Mathf.Lerp is called. If currentSpeed started at 0, it will be set to half of targetSpeed. The next time Mathf.Lerp is called, another 0.5 seconds has passed, so currentSpeed will increase by 50% of the difference between targetSpeed and currentSpeed, which means that it increases by 0.5 x 0.5 targetSpeed = 0.25 x targetSpeed; thus putting currentSpeed at 0.75 x targetSpeed. Next frame, you end up at 0.875 targetSpeed, and so on.

As you can see, currentSpeed only gets halfway to where it wants to go each frame, thereby taking infinitely long to reach the target speed.

This may suggest that things should get worse with higher frame-rates, since then currentSpeed will move less towards targetSpeed in each frame. For example, if your frame rate is 60fps, then currentSpeed will only move 1/60th of the way to targetSpeed in each frame. Luckily, mathematics tells us that this sort of behaviour converges nicely, so you will never end up short of the targetSpeed, it will just take you longer.

Even more math:

After a single frame, the difference between targetSpeed and currentSpeed is
diff = (1-1/framerate) x (targetSpeed - currentSpeed)

Example: if you’re running at 60 fps, currentSpeed will move 1/60th of the way towards targetSpeed, which means that (1-1/60) = 59/60 of the way to go remains.

Thus, after N frames have passed, the difference will be
diff(N) = (1 - 1/frameRate)^N x (targetSpeed - currentSpeed).

We already know how Lerping works on stone age computers: a slow frame rate (less than 1 fps) will make currentSpeed hit targetSpeed in a single frame. What about insanely fast futuristic supercomputers? Will the Lerp be reeeeeally slow? As it turns out, nope, there is a limit to how slow it will progress (albeit it will still take infinitely long to hit the target exactly).

What we need to do to check this is to replace N as a variable by (framerate x timePassed) and calculate the limit as the framerate goes to infinity. Luckily, the limit (1-1/y)^y (y->infinity) is a well known one; it happens to be the famous mathematical number e (of the exponential function Exp()). The end result:

diff = Exp(-timePassed) x (targetSpeed - currentSpeed).

So the difference falls off exponentially. If you want to include your acceleration parameter, then you have

diff = Exp(-acceleration x timePassed) x (targetSpeed - currentSpeed)

Note that timePassed is the time since the Lerp began and not the deltaTime.