GDKB

Dot Product

Intermediate25 Minutes readUpdated July 21, 20263 related concepts

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.

On this page

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 why 1 means identical direction and -1 means 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)

text
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)

csharp
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)

cpp
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.

csharp
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 Dot when 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 0 means "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.

csharp
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

  1. Compute the dot product of (1, 0) and (0, 1) by hand and confirm it equals 0, then explain what that result means geometrically.
  2. Take the field-of-view example and compute the correct fovDotThreshold value for a 90-degree total field of view (45-degree half-angle), using cos(45°) ≈ 0.707.
  3. 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.
  4. 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.
  • 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

Related Concepts