Steering Behaviours

Watch a hawk stoop onto a pigeon, a shopper thread through a crowd, or a sheepdog peel a straggler back into the flock, and you are watching the same thing: a body that wants to be somewhere, turning and accelerating toward that want without ever plotting a global route. It reacts to what is near, moment by moment, and the path emerges. In 1999 Craig Reynolds — the same researcher whose flocking and boids gave us digital starlings — bottled this into a small, composable vocabulary he called steering behaviours. It is the reason game characters, crowd extras and swarming insects move as if they had somewhere to be.

The magic is that a whole zoo of life-like motion — chasing, fleeing, wandering, dodging obstacles, threading a corridor — comes from one tiny machine plus a catalogue of one-line formulas. This page builds the machine, walks the catalogue, and shows precisely why seek orbits a target forever while arrive eases to a graceful stop.

The vehicle: one tiny update loop

Every steering agent is a vehicle: a point with a position \mathbf{p}, a velocity \mathbf{v}, a mass m, and two governors — a maximum speed v_{\max} (how fast it can go) and a maximum force f_{\max} (how hard it can turn or brake). Each frame it computes a single steering force, then runs the most famous four lines in game AI:

That is the entire engine. The clamps are what make it look alive: capping the force means the vehicle cannot snap instantly onto a new heading — it must curve, banking into turns with momentum, the way a real body does. Capping the speed keeps it from accelerating forever. Everything below is just a different recipe for that first line, the raw force \mathbf{F}.

The universal trick: desired minus current

Almost every behaviour shares one idea. You describe the velocity you wish you had — the desired velocity \mathbf{v}_d — and then steer by the difference between the wish and reality:

\mathbf{F}_{\text{steer}} \;=\; \mathbf{v}_d - \mathbf{v}.

Geometrically that difference vector points exactly the way you must push to rotate your current velocity toward the desired one, and its length says how urgently. Clamp it to f_{\max} and feed it to the update loop. Change the recipe for \mathbf{v}_d and you change the personality — that is the whole catalogue.

The catalogue

BehaviourDesired velocity (the idea)
SeekHead straight at a target at full speed.
FleeHead directly away from a target at full speed.
ArriveSeek, but ramp speed down to zero inside a braking radius — no overshoot.
PursueSeek the predicted future position of a moving target.
EvadeFlee the predicted future position of a moving threat.
WanderSteer toward a slowly-jittering point on a circle projected ahead — natural meandering.
Path followingSteer back toward a spline/corridor when you drift off it.
Obstacle / wall avoidanceSteer away from a predicted collision with a circle or wall ahead.
Flow-field followingDesired velocity is read straight from a vector field sampled at your position.

Notice the family resemblances. Flee is seek with a minus sign. Pursue is seek aimed at where the target will be; evade is flee from that same prediction. Arrive is seek with a speed dial. Master seek and you have half the list for free.

Seek and arrive, side by side

Below, an agent sits with some current velocity (the solid arrow). The target is on a slider — drag it. The desired velocity points from the agent to the target; the steering force (dashed arrow) is desired minus current, the push that rotates the agent's heading toward the target. The faint circle is the braking radius: an arrive agent inside it wants a slower desired speed, scaled down toward zero at the centre, so it eases in instead of barrelling through.

Slide the target far away and near: notice the steering arrow always aims the agent's turn, and — for arrive — shrinks as the target enters the braking circle. That shrinking is the whole difference between a smooth landing and an endless orbit.

Worked example: seek

Put the agent at \mathbf{p} = (0,0) with current velocity \mathbf{v} = (2, 0) (moving right), v_{\max} = 4, f_{\max} = 1, mass 1, and a target at \mathbf{t} = (0, 3) (straight up).

1. Desired velocity — full speed straight at the target:

\mathbf{v}_d = \widehat{(\mathbf{t} - \mathbf{p})}\; v_{\max} = \widehat{(0,3)}\cdot 4 = (0,1)\cdot 4 = (0, 4).

2. Steering = desired − current:

\mathbf{F} = \mathbf{v}_d - \mathbf{v} = (0,4) - (2,0) = (-2, 4).

3. Clamp to f_{\max} = 1. Its length is \sqrt{(-2)^2 + 4^2} = \sqrt{20} \approx 4.47, so we scale it down to length 1:

\mathbf{F} = (-2, 4)\cdot\frac{1}{4.47} \approx (-0.45,\, 0.89).

4. Integrate (mass 1, so \mathbf{a} = \mathbf{F}): \mathbf{v} + \mathbf{a} = (2,0) + (-0.45, 0.89) = (1.55, 0.89), length \approx 1.79 < v_{\max} so no speed clamp needed; the agent's heading has rotated up-and-left, curving toward the target rather than teleporting onto it. Do this every frame and it sweeps a smooth arc onto the target — then, being plain seek, sails right through and swings back.

Arrive: seek with the brakes on

Arrive keeps the same desired direction as seek but scales the desired speed by how far you are inside a braking radius r. Let d = \lVert \mathbf{t} - \mathbf{p}\rVert be the distance to the target:

\text{speed} = v_{\max}\cdot \min\!\left(1,\; \frac{d}{r}\right), \qquad \mathbf{v}_d = \widehat{(\mathbf{t} - \mathbf{p})}\;\text{speed}.

Outside the radius (d \ge r) the factor is 1 and arrive is seek. Inside it, the desired speed shrinks linearly with distance, hitting 0 exactly at the target. So as the agent closes in, its desired velocity collapses, the steering force gently opposes its motion, and it decelerates to a dead stop on the target — no overshoot, no orbit. That single \min(1, d/r) factor is the difference between a car parking and a moth around a lamp.

That is pursue. If you seek a moving target's current position you are always aiming behind it — you tail-chase, curving into its wake. Pursue instead estimates where the target will be after a short lookahead T and seeks that: \mathbf{t}_{\text{future}} = \mathbf{t} + \mathbf{v}_{\text{target}}\,T. A neat touch is to make T proportional to the current gap, so a distant quarry gets a bigger lead-prediction. Flip the sign — flee that predicted point instead of seeking it — and you have evade, the prey that cuts away from where the hunter is about to be. Predators and prey, from one lookahead term.

Because the randomness is applied to a heading, not a position, and only a little each frame. Wander projects a small circle a short distance ahead of the agent and keeps a target point on that circle's rim. Each frame it nudges that point by a tiny random jitter along the rim, then seeks it. Because the point can only drift gradually around the circle, the heading changes smoothly — the agent meanders like a grazing animal instead of teleporting to a new random direction every frame (which would look like a twitching bug). The circle's radius sets how sharply it can turn; the jitter sets how restless it is.

Combining behaviours

Real characters do several things at once: seek a goal while dodging walls while keeping some wander. Reynolds gives three ways to fuse the individual steering forces into one.

The choice matters. A blind weighted sum is simple and often fine, but in a tight spot the avoid force and the seek force can nearly cancel and the agent drifts straight into the wall it was trying to dodge. Priority-based blending guarantees the life-or-death behaviour wins.

Two classic traps. First: plain seek never slows down. Its desired speed is always v_{\max}, so an agent that reaches its target still has full velocity, sails past, whips around, and orbits the target forever like a moth round a bulb. If the thing must stop — a car parking, a guard reaching a post — use arrive, which ramps the desired speed to zero inside the braking radius. Never use bare seek for a destination that has to be held.

Second: combining behaviours by a naive sum can go badly wrong. Opposing forces (seek pulling right, avoid pushing left) can cancel, leaving the agent frozen or drifting into danger; or many aligned forces can exceed f_{\max} so hard that the clamp throws away everything but the loudest one. Don't just add and hope — weight the forces deliberately, or use priority so avoidance always overrides seek.

Why this is the workhorse of game AI

Steering behaviours are local, reactive, and cheap: no search, no map, just a force computed from what's nearby, run per agent per frame. Stack them and you get crowds, traffic, fish schools, RTS unit movement and enemy chase logic — all from position, velocity, two clamps, and a handful of one-line desired-velocity formulas. They pair naturally with a global planner (A* finds the corridor; path-following steering walks it smoothly), and they are the direct ancestor of the flocking rules you will meet next.