Gameplay math — vectors, quaternions and interpolation instead of hand-rolled arithmetic
When people say "math in Unreal" they really mean six building blocks that cover 95% of gameplay tasks: FVector for positions and directions, the dot product for angles and projections, FTransform for switching between spaces, FQuat for rotations without gimbal lock, line traces for world queries, and FInterpTo/Slerp for smooth motion. Each has one canonical use — and a dozen wrong ones.
The classic beginner mistake is writing math by hand instead of using the ready API: adding Euler angles component-wise, normalising via sqrt(x*x+y*y+z*z), interpolating a rotation linearly. Unreal already provides FQuat::Slerp, GetSafeNormal, FMath::RInterpTo — they handle the edge cases (zero vector, shortest-path on the sphere, frame-rate independence). A custom replacement almost always breaks on a zero input or a large DeltaTime.
The second recurring confusion is dot product (Dot → scalar, angle/projection) vs cross product (Cross → vector, normal/side). They are not interchangeable. The third is FRotator (angles for UI and the editor) vs FQuat (internal representation, the only safe form for composition). The full map lives in the layers below.
Topic map
- Vectors —
FVector, units (cm),Size/SizeSquared,GetSafeNormal, basic ops. - Dot Product —
Dot, cosine of the angle, projection, cone of vision, front/back half-space. - Transforms —
FTransform(loc/rot/scale), world vs local,TransformPosition/InverseTransformPosition. - Quaternions —
FQuatvsFRotator, gimbal lock, composition by multiplication,MakeFromX. - Raycasting —
LineTraceSingleByChannel,FHitResult, sweeps, channels vs profiles,FCollisionQueryParams. - Interpolation —
Lerp/Slerp/Nlerp,FInterpTovsFInterpConstantTo, exponential smoothing and FPS independence.
Common traps
| Mistake | Consequence |
|---|---|
Passing a direction to LineTraceSingleByChannel instead of the world-space End point | Ray heads toward world (0,0,0); nothing is hit |
Forgetting to normalise vectors before Dot | The result is not a cosine — every cos(angle) comparison is meaningless |
Treating the Dot result as an angle in degrees | It's a cosine; needs acos and RadiansToDegrees |
Adding FRotators component-wise | Accumulates gimbal lock; the right path is FQuat * FQuat |
Moving an actor as Pos += Direction * Speed without * DeltaTime | Speed depends on FPS |
Using Lerp(A, B, Speed * DeltaTime) for smoothing | At large DeltaTime the step exceeds 1, the target is overshot, oscillations appear |
Reading FHitResult before checking the bool return | Fields are not filled on miss — garbage or zeros |
SetActorLocation to move a character | Bypasses CharacterMovementComponent and the NavMesh; clips through walls |
Using Size instead of SizeSquared for comparisons | Pays a sqrt per frame; hot spot at scale |
Reading GetActorForwardVector right after SetActorRotation in the same frame | The forward cache is refreshed, but the FQuat axis may differ from expectations at extreme angles |
Interview relevance
Gameplay math is a middle-level topic for any UE5 gameplay interview. Checks:
- That
Dotyields a scalar (cosine of the angle),Crossyields a vector (perpendicular). - Why
FQuatexists ifFRotatordoes — gimbal lock and safe composition. - How
FTransformis built (loc/rot/scale) and whyInverseTransformPositionexists. - How to make smoothing frame-rate independent (exponential, not linear).
- That
LineTraceSingleByChanneltakes anEndpoint, not a direction. - The difference between trace channels and collision profiles.
Common wrong answer: "I add angles and normalise vectors by hand with a square root — that's enough for any gameplay." The real answer: Unreal ships ready types and operations that already solve a known class of bugs (gimbal lock, zero vector, overshoot at low FPS). Hand-rolled math bypasses those solutions and brings every trap back.