For twenty years, character locomotion was built like a subway map. Animators authored a
Their replacement, motion matching, keeps no states and no transitions at all. It
keeps only a big pile of
Strip motion matching down and it is a search running on a clock. Every
There is no notion of "being in the walk state". The character is only ever at a frame of raw data, and the search is free to leap to any other frame — inside the same clip or a completely different one — the instant a better match exists. The database's job is to be rich enough that some frame always fits; the search's job is to find it fast.
Everything hinges on the feature vector — the handful of numbers that summarise a frame for comparison. Compare full skeletons (dozens of joint angles) and the search is both slow and wrong-headed; matching should care about the things a player feels. So the feature vector blends three ingredients:
These live in different units — metres, metres-per-second, radians — so they cannot simply be thrown
into one distance. Each block gets a weight, and the matching cost is a
weighted squared distance (a weighted
The chosen frame is simply the cheapest one, a nearest-neighbour query in feature space:
Crank up the trajectory weights and the character becomes twitchy and hyper-responsive but may snap between poses; crank up the pose and foot weights and it moves smoothly but lags behind the stick. Those weights are the tuning dials of the whole system.
Here the player is holding "turn left while running". The dashed path is the desired future trajectory — the query — a few sample points curving up and to the left of the character's current position. Around it sit three candidate database trajectories, each stored with some frame of mocap. The search scores each by how well its sample points line up with the desired ones (plus pose and foot terms we can't draw); the best match, candidate B, is highlighted. That is the frame we jump to.
Notice the search compares trajectories, not just endpoints: candidate C ends near the goal but bends the wrong way through the middle, so its per-point cost is high. Candidate A barely turns at all. Only B curves left through every sample, so it minimises the summed cost.
Let's compute a match by hand with a deliberately small feature vector. We'll use two future trajectory points and two foot positions, all in a flat 2-D world (units in metres), and drop the pose term for clarity. The query — "turn left while running" — is
We weight the trajectory block by
| Frame | traj pt 1 | traj pt 2 | foot 1 | foot 2 |
|---|---|---|---|---|
| A (gentle left) | (1.1, 0.5) | (1.5, 1.3) | (-0.1, 0.0) | (0.0, 0.3) |
| B (hard right) | (1.0, -0.6) | (1.4, -1.5) | (-0.1, 0.0) | (0.1, 0.2) |
Frame A. Trajectory squared error:
Frame B. Its feet match perfectly, but it turns the wrong way. Trajectory squared
error:
Frame A wins by a mile (
A shipping locomotion database can hold tens or hundreds of thousands of candidate frames, and we
re-query several times a second, so a naive scan sounds ruinous. Two things save it. First, the
feature vector is tiny — a couple of dozen floats — so scoring one frame is a handful of
multiply-adds, and even a brute-force sweep of the whole database is cheap on modern hardware (it
vectorises beautifully). Second, when the database gets big you swap the brute-force scan for a spatial
index — a
The obvious cost of motion matching is memory: you ship the raw mocap. In 2020 Daniel Holden, Oussama Kanoun and colleagues introduced Learned Motion Matching, which trains small neural networks to reproduce the behaviour of the search and the clips without storing them. One network compresses the pose data; another predicts the next feature vector given the current one (a learned "stepper"); a third decompresses features back into full poses. The result matches the quality of classic motion matching at a fraction of the memory — a few megabytes of network weights instead of hundreds of megabytes of animation — while keeping the same responsive, search-driven feel. It is the bridge from the data-driven era to the learned-motion era.
Motion matching feels like magic, but it has no imagination — it can only ever return a frame that is already in the database, scored by the weights you chose. Two failure modes follow directly, and both look like the character behaving badly:
The slogan: motion matching is only as good as your database coverage and your feature weights. Debugging it is usually asking "is the right motion in the data?" and "are the weights sane?" — before touching the search itself.
Set against the sprawling, hand-wired graphs it replaced, motion matching trades authoring labour for data and compute — a bargain that got better every year as memory grew cheaper, and better still once Learned Motion Matching shrank the memory cost too.