Dot, Cross & Reflect
Three small tools for working with directions: Dot ("is it in front of me?"), Cross ("which way is sideways?") and Reflect ("which way does it bounce?").
Think of a game of pool. Dot is asking "how much is the ball heading toward that pocket?" Cross is finding the direction that points straight up out of the table. Reflect is the ball bouncing off a cushion.
First: getting a direction
Most of these tools need a direction, an arrow with length 1. To get one from two positions, subtract and normalize:
Vector3 toTarget = target.position - transform.position; // arrow from me to target
float distance = toTarget.magnitude; // how long the arrow is
Vector3 dir = toTarget.normalized; // same arrow, length 1
Remember: target minus me points from me to the target.
Dot: how much do two arrows agree?
Vector3.Dot(a, b) gives back one number. If both arrows have length 1:
| Dot result | Meaning |
|---|---|
1 | Same direction |
0.5 | About 60° apart |
0 | At a right angle (sideways) |
-1 | Opposite directions (behind) |
So "is the player in front of me?" is just Dot(transform.forward, dirToPlayer) > 0.
Example: a guard's view cone
Attach to a guard, assign a target and watch the line in the Scene view: green = seen, red = not seen.
using UnityEngine;
public class ViewCone : MonoBehaviour
{
[SerializeField] private Transform target;
[SerializeField, Range(0, 180)] private float viewAngle = 90f; // total cone width
[SerializeField] private float range = 10f;
void Update()
{
if (target == null) return;
Vector3 toTarget = target.position - transform.position;
if (toTarget.magnitude > range) { Draw(false); return; }
// cos(half the angle) is the smallest Dot that still counts as "inside"
float minDot = Mathf.Cos(viewAngle * 0.5f * Mathf.Deg2Rad);
bool seen = Vector3.Dot(transform.forward, toTarget.normalized) >= minDot;
Draw(seen);
}
void Draw(bool seen) =>
Debug.DrawLine(transform.position, target.position, seen ? Color.green : Color.red);
}
The cone doesn't know about walls. Add a Physics.Raycast if walls should block sight.
Cross: the arrow at right angles to both
Vector3.Cross(a, b) gives an arrow that is perpendicular to both a and b. Lay two pencils flat on a desk; their cross product points straight up out of the desk (or straight down, if you swap the order).
| Use | Code |
|---|---|
| "Right" from a forward direction | Vector3.Cross(Vector3.up, forward) |
| The way a triangle faces (its normal) | Vector3.Cross(b - a, c - a).normalized |
| Is the target to my left or right? | Vector3.Cross(transform.forward, dir).y: positive = right, negative = left |
If the two arrows point along the same line, the result is zero: there's no single "sideways" answer.
Reflect: bouncing
Vector3.Reflect(direction, normal) returns the direction after a perfect bounce. The normal is the arrow sticking straight out of the surface; a raycast hit gives it to you as hit.normal.
Example: a bouncing laser preview
using UnityEngine;
public class BouncePreview : MonoBehaviour
{
[SerializeField] private int maxBounces = 4;
[SerializeField] private float maxDistance = 30f;
void Update()
{
Vector3 origin = transform.position;
Vector3 dir = transform.forward;
for (int i = 0; i <= maxBounces; i++)
{
if (!Physics.Raycast(origin, dir, out RaycastHit hit, maxDistance))
{
Debug.DrawRay(origin, dir * maxDistance, Color.yellow);
break;
}
Debug.DrawLine(origin, hit.point, Color.yellow);
dir = Vector3.Reflect(dir, hit.normal);
origin = hit.point + hit.normal * 0.01f; // step off the wall so we don't hit it again
}
}
}
Bonus: sliding along a wall
Reflect bounces. To slide along a wall instead (like a character pushing into it), remove the part of the movement that goes into the wall:
Vector3 slide = Vector3.ProjectOnPlane(velocity, hit.normal);
Common Mistakes
- Forgetting to normalize before
Dot. With longer arrows the result is bigger than 1 and your angle checks break. - Subtracting the wrong way round (
me - target) and getting an arrow pointing away. - Swapping the inputs to
Crossand getting "left" instead of "right". - Starting the next ray exactly on the wall, so it hits the same wall again. Nudge it off along the normal.
See also
This page is a simplified, AI-assisted interpretation. For the complete and authoritative reference, see the official documentation.