There are two common patterns for use of Lerp. The one you're using is:
current = Lerp(current, target, sharpness)
(where sharpness is a constant between 0 and 1)
Note that there's a feedback loop here. The value of current
is both an input and an output, so the value of current
we use as input in the next frame is the output from the last frame.
This is good for when you want an easing effect: when the target
is updated to something far from current
, you get a fast initial movement, which slows down as the current
value approaches the target
. This looks nice in UI transitions and simple camera follow scripts.
In the context of interpolation for multiplayer though, it's probably not an ideal choice. Imagine another player running at a constant velocity across my screen. Their speed will spike each time I get a new update from the server (when target
jumps ahead) and then slow to a crawl as they get close to the last update position. Even if I'm getting frequent updates, the constant increases & decreases in speed make it look jerky and low-performance.
Instead you probably want the other common Lerp pattern:
current = Lerp(previous, next, progress)
(where progress varies linearly from 0 to 1 over the expected duration of the move)
Here you store the position of the player in the most recent update from the server (next
), and the position they were in when it was received (previous
), and interpolate between them over one server update interval.
Note that neither of the inputs previous
or next
are modified by the Lerp, which prevents any feedback loop changing the behaviour of the formula over time.
Instead, the character moves with a constant velocity throughout the Lerp. In fact, if you let progress
go past 1 in the event of a late or missing update packet from the server, then this also seamlessly handles a simple linear prediction, so the character won't stop and hesitate waiting for new server input (but at a risk of slight overshoot). This will generally look much smoother for this type of use.