Linear Interpolation (Lerp)
Summary
Linear interpolation — "lerp" — computes a value part-way between a start
and an end value, based on a fraction t between 0 (exactly the start)
and 1 (exactly the end). Lerp(0, 10, 0.5) gives 5 — halfway between
them. Lerp works identically on plain numbers, positions, colors, and
rotations, making it one of the most widely reused building blocks for
smoothing movement, fading effects, and blending values gradually instead
of snapping between them instantly.
Why This Matters
Instantly snapping a value from one state to another — a camera jumping to a new position, a health bar jumping to a new fill amount, a color switching abruptly — reads as jarring and mechanical, even when the underlying logic is completely correct. Games feel more polished when values transition smoothly over time instead of jumping. Lerp gives a single, simple, reusable formula for "smoothly move from A toward B" that applies identically whether A and B are numbers, positions, colors, or angles, without needing a bespoke smoothing solution for each different kind of value.
Mental Model
Lerp is a dimmer switch, not an on/off light switch. Flipping a light
switch snaps a room from fully dark to fully lit instantly, with nothing
in between. A dimmer switch, by contrast, lets you land anywhere along
that range — 20% lit, 50% lit, 90% lit — smoothly, by turning the same
dial further or less far. t in a lerp call is that dial: 0 is fully
"start," 1 is fully "end," and anything in between is a proportional
blend of the two.
Core Explanation
- The core formula is
start + (end - start) * t. This computes the offset between start and end (end - start), scales that offset by the fractiont, and adds it back onto the start value — producing a value proportionally between the two. tis typically, but not always, clamped between 0 and 1. A clamped lerp guarantees the result stays within the start-to-end range; an unclamped variant allowstvalues outside0–1to extrapolate past either endpoint, which some specific use cases intentionally rely on.- Lerp generalizes to any type that supports subtraction and scaled
addition. Numbers,
Vector3positions, and colors all lerp using the identical formula shape — engines provideLerpoverloads for each, applying the same math component-wise. - Lerping every frame toward a moving target, with a fixed
t, produces a natural "ease out" deceleration. RecomputingLerp(current, target, fixedFraction)every frame (rather than lerping once with a fixed duration) causes movement to be fast when far from the target and progressively slower as it approaches — a frequently-used "smooth follow" pattern, distinct from a duration-based lerp.
Syntax / Theory
Engine-neutral (formula)
lerp(start, end, t) = start + (end - start) * t
t = 0 → result = start
t = 0.5 → result = halfway between start and end
t = 1 → result = end
C# (Unity)
float health = Mathf.Lerp(0f, 100f, 0.75f); // 75.
Vector3 pos = Vector3.Lerp(pointA, pointB, 0.5f); // Halfway between two positions.
Color faded = Color.Lerp(Color.white, Color.clear, fadeAmount);
C++ (Unreal)
float Health = FMath::Lerp(0.f, 100.f, 0.75f);
FVector Pos = FMath::Lerp(PointA, PointB, 0.5f);
Both engines provide type-specific Lerp overloads (numbers, vectors,
colors) that all apply the same underlying formula — learning it once
covers every one of these variants.
Practical Example
A duration-based fade smoothly transitions a UI element's opacity over a
fixed amount of time, using elapsed time divided by duration as t.
public class FadeCanvas : MonoBehaviour
{
public float duration = 1f;
private float elapsed;
void Update()
{
elapsed += Time.deltaTime;
float t = Mathf.Clamp01(elapsed / duration); // 0 at start, 1 once duration has passed.
canvasGroup.alpha = Mathf.Lerp(1f, 0f, t);
}
}
Dividing elapsed time by the total duration produces exactly the 0-to-1
progress value lerp expects — this pattern (elapsed / duration, clamped)
is the standard way to drive any duration-based lerp.
Common Mistakes
- Confusing a fixed-
t-per-frame "smooth follow" lerp with a duration-based lerp, and expecting the former to finish in a specific time.transform.position = Vector3.Lerp(transform.position, target, 0.1f)called every frame never truly reaches the target in a fixed time — it asymptotically approaches it, getting closer forever without quite arriving, which is a different (and frame-rate-dependent, unless adjusted) behavior than a duration-based lerp. - Not clamping
twhen a clamped result was intended. An unclampedtgreater than1or less than0extrapolates past the start/end values — appropriate for some effects, a bug for others (like a fade that should never go past fully transparent or fully opaque). - Using plain lerp for rotations instead of a rotation-aware
interpolation. Lerping between two rotations represented as raw angles
or quaternions component-wise can produce incorrect, non-smooth results
near the "wraparound" point —
Slerp(spherical linear interpolation) exists specifically to interpolate rotations correctly. - Applying a fixed-
t-per-frame lerp without accounting for delta time, making the "smooth follow" speed vary with frame rate — a frame-rate-independent version typically needs thetvalue itself derived from delta time, not used as a flat constant.
Game Development Example
A camera smoothly follows the player using the fixed-fraction-per-frame lerp pattern, producing natural deceleration as it catches up.
public class SmoothCameraFollow : MonoBehaviour
{
public Transform target;
public float followSpeed = 5f;
void LateUpdate()
{
float t = 1f - Mathf.Exp(-followSpeed * Time.deltaTime); // Frame-rate-independent factor.
transform.position = Vector3.Lerp(transform.position, target.position, t);
}
}
The camera moves quickly when far from the player and gradually slows as it gets close, producing smooth, natural-feeling tracking rather than a rigid, instantly-locked follow.
Best Practices
- Use duration-based lerp (elapsed / total time, clamped) when a value needs to reach its target in a specific, predictable amount of time.
- Use fixed-fraction-per-frame lerp for "smooth follow" style effects, accounting for delta time to keep the behavior frame-rate independent.
- Use
Slerpinstead of plainLerpwhen interpolating rotations. - Clamp
tto0–1unless deliberately relying on extrapolation beyond the start/end range.
Exercises
- Compute
Lerp(10, 20, 0.25)by hand using the formula, then verify it in code. - Take the
FadeCanvasexample and changedurationto3f— describe what changes about the rate at whichtincreases per frame, and confirm the fade still completes at the same final alpha value. - You're building a health bar that should visibly "catch up" over about half a second whenever the player takes damage, rather than snapping instantly. Decide between a duration-based lerp and a fixed-fraction smooth-follow lerp for this, and justify the choice.
- Research why
Vector3.Lerpinterpolates in a straight line between two points whileVector3.Slerpinterpolates along an arc, and explain a situation (such as orbiting) where the arc-based version produces a visibly better result.
Related Concepts
- Vectors — lerping a position applies the identical formula to a
Vector3component-wise, building directly on vector arithmetic. - Delta Time — frame-rate-independent, fixed-fraction lerp specifically
depends on incorporating delta time into the
tcalculation, tying the two concepts together in the smooth-follow pattern. - Direction Vectors — interpolating between two directions correctly
generally requires
Slerprather than plainLerp, a nuance that builds on understanding what a direction vector represents.
Further Reading
KNOWLEDGE_SCHEMA.md— GDKB's concept maturity ladder and cross-linking rules, which this document follows.- Unity documentation — Vector3.Lerp and Mathf.Lerp: https://docs.unity3d.com/ScriptReference/Vector3.Lerp.html
- Unreal Engine documentation — FMath::Lerp: https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Math/UnrealMathUtility