Dot Product
Summary
The dot product takes two vectors and produces a single number describing
how aligned they are — pointing the same way gives a large positive
number, perpendicular gives zero, and pointing opposite ways gives a large
negative number. When both inputs are unit vectors (see [[CON-0045]]),
that number ranges neatly from 1 (identical direction) through 0
(perpendicular) to -1 (opposite direction), making the dot product one of
the most widely used tools for field-of-view checks, lighting calculations,
and "is this in front of or behind me" questions.
Why This Matters
Many gameplay questions are really asking "how aligned are these two
directions" — is the target in front of the player, is a surface facing
the light, is the enemy looking at me. Answering this with angles directly
usually means computing an angle in degrees and comparing it to a
threshold, which involves an expensive inverse trigonometric function
(acos) just to end up doing a simple greater-than/less-than comparison
anyway. The dot product skips the angle entirely — it produces a number
that already increases and decreases exactly the way alignment does,
letting you compare directly against a threshold without ever computing an
actual angle.
Mental Model
The dot product is a shadow's length, not the angle that cast it. Imagine one vector as a stick standing upright and a second vector as the ground it's being "projected" onto based on the angle between them. When the stick points straight along the ground direction, its shadow is as long as possible; as it tilts toward perpendicular, the shadow shrinks to nothing; tilt past that, and the "shadow" reverses. The dot product is exactly that projected length — a single number that naturally grows, shrinks, and flips sign as the angle between two vectors changes, without ever needing to name the angle itself.
Core Explanation
- Computed by multiplying matching components and summing.
dot(A, B) = Ax*Bx + Ay*By + Az*Bz— each axis contributes its own product, and those products are added together into one final number. - The sign tells you the general relationship. Positive means the vectors broadly point the same way (angle less than 90°); zero means exactly perpendicular; negative means broadly opposite (angle greater than 90°) — this alone answers many "in front of / behind" questions without further calculation.
- With unit vectors, the result equals the cosine of the angle between
them.
dot(unitA, unitB) = cos(angle)— this is why1means identical direction and-1means opposite: those are the cosine values of 0° and 180° respectively. - Unlike the cross product (see [[CON-0049]]), the dot product produces a single number (a scalar), not a vector. The two operations answer fundamentally different questions — "how aligned" versus "what's perpendicular to both" — and shouldn't be confused despite both taking two vectors as input.
Syntax / Theory
Engine-neutral (formula)
dot(A, B) = Ax*Bx + Ay*By + Az*Bz
If both A and B are unit vectors:
dot ≈ 1 → same direction
dot ≈ 0 → perpendicular
dot ≈ -1 → opposite direction
C# (Unity)
float alignment = Vector3.Dot(transform.forward, directionToTarget);
if (alignment > 0.7f) // Roughly within a 45-degree cone in front.
{
// Target is broadly in front of this object.
}
C++ (Unreal)
float Alignment = FVector::DotProduct(GetActorForwardVector(), DirectionToTarget);
if (Alignment > 0.7f)
{
// Equivalent field-of-view check.
}
Both engines expose Dot/DotProduct as a direct built-in, taking two
Vector3/FVector values and returning a single float — no manual
component multiplication needed, though understanding the formula makes
the resulting number's meaning obvious rather than "magic."
Practical Example
A stealth game checks whether the player is within an enemy's field of view using the dot product instead of computing an actual angle.
bool IsInFieldOfView(Transform enemy, Transform player, float fovDotThreshold)
{
Vector3 directionToPlayer = (player.position - enemy.position).normalized;
float alignment = Vector3.Dot(enemy.forward, directionToPlayer);
return alignment >= fovDotThreshold; // e.g. 0.766 for a 40-degree half-angle FOV.
}
fovDotThreshold is precomputed once as cos(desiredAngle) — comparing a
dot product result directly against it avoids computing acos on every
single check, every frame, for every enemy.
Common Mistakes
- Forgetting to normalize inputs when the result needs to represent an actual cosine/angle relationship. A dot product between two non-unit-length vectors is still mathematically valid, but its magnitude is scaled by both vectors' lengths, making it meaningless as a direct stand-in for "how aligned" without also accounting for those lengths.
- Confusing the dot product with the cross product. Reaching for
Dotwhen a perpendicular vector was actually needed (or vice versa) produces a completely different kind of result — a single number instead of a vector, or vice versa — see [[CON-0049]] for the distinction. - Converting a dot product result back into an angle unnecessarily.
Calling
Mathf.Acos(dotResult)just to then compare the resulting angle against a threshold throws away the entire performance benefit of using the dot product in the first place — compare the raw dot value against a precomputed cosine threshold instead. - Assuming a dot product of exactly
0means "never happens" and skipping the perpendicular case. Exactly perpendicular vectors are a legitimate and fairly common result (e.g. checking if a surface is exactly vertical) — code should handle it explicitly rather than assuming it won't occur.
Game Development Example
A simple lighting calculation uses the dot product between a surface's normal and the direction to a light source to determine how directly the surface is lit.
float lightIntensity = Mathf.Max(0f, Vector3.Dot(surfaceNormal, directionToLight));
finalColor = baseColor * lightIntensity;
A surface facing directly at the light gets full intensity (dot ≈ 1); a
surface facing away gets none (dot clamped to 0 instead of going
negative, since negative light makes no physical sense) — this is
essentially the mathematical foundation of diffuse (Lambertian) lighting,
one of the dot product's most common real-world graphics applications.
Best Practices
- Normalize both inputs before treating a dot product result as a cosine value or angle-based threshold comparison.
- Precompute a comparison threshold as a cosine value (
cos(desiredAngle)) once, rather than converting a dot product result back to an angle on every check. - Use the sign of a dot product for quick in-front/behind or same- side/opposite-side checks before reaching for a more expensive calculation.
- Reach for the cross product instead when the actual perpendicular direction — not just an alignment measurement — is what's needed.
Exercises
- Compute the dot product of
(1, 0)and(0, 1)by hand and confirm it equals0, then explain what that result means geometrically. - Take the field-of-view example and compute the correct
fovDotThresholdvalue for a 90-degree total field of view (45-degree half-angle), usingcos(45°) ≈ 0.707. - You're building a cover system where an enemy should only take cover from threats roughly in front of them, not from behind. Decide how to use the dot product to implement this check, and justify the threshold value you'd choose.
- Research how the dot product is used in backface culling (deciding whether a 3D triangle is facing toward or away from the camera) and explain, in your own words, which two vectors are compared and what sign of the result indicates the triangle should be culled.
Related Concepts
- Direction Vectors — the dot product's most meaningful use cases operate specifically on direction vectors (unit length), tying the two concepts directly together.
- Cross Product — the other fundamental vector-pair operation, producing a perpendicular vector instead of an alignment number; understanding both side by side clarifies when to reach for each.
- Vector Normalization — normalizing inputs first is what makes a dot product's result interpretable as a cosine value rather than an arbitrarily-scaled number.
Further Reading
KNOWLEDGE_SCHEMA.md— GDKB's concept maturity ladder and cross-linking rules, which this document follows.- Unity documentation — Vector3.Dot: https://docs.unity3d.com/ScriptReference/Vector3.Dot.html
- Unreal Engine documentation — FVector::DotProduct: https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/Math/FVector