The equation
A value that chases another value
Take any number you want animated — a position, an angle, a scale — and don't set it. Give it a target instead, and let it move like a mass on a spring with a damper attached.
That is the line at the top of this page. Read it as: where I am, plus a little of how fast I'm going, plus a little of how that is changing, should equal where the target is, plus a little of where the target is heading. The output never jumps. It surges, overshoots, rings, settles.
You do not set k₁, k₂ or k₃. They are derived from three parameters chosen to mean something to a person, which is the contribution that makes this usable — f, z and r. Move them below. The dashed line is the target; the purple line is the output. Tap the plot to move the target somewhere it wasn't expecting.
The engine's own SecondOrderScalar, imported by this page.
Everything else in this article is that class, wired to more and more of a body.
The three parameters
What f, z and r each buy you
That last one is worth stopping on. A negative r makes a value wind up in the wrong direction before travelling — which is anticipation, the first thing in every animation textbook, produced here by a minus sign rather than by a drawing. Nothing in the code knows what anticipation is.
The overshoot that z < 1 produces is doing similar work. A value that arrives, passes its mark, comes back and settles reads as having mass. A value that arrives exactly reads as a mechanism. Neither is more correct; one is just alive.
The two bodies
Crisp logic, and a body that lags it
There are two creatures inside each other. The first is ordinary game code: a position, a velocity, a jump arc under gravity. It is always exactly where it should be, and it is never drawn.
The second is the body you see, and every visible part of it is a spring chasing something about the first one. Nothing is chased twice with the same tuning, and the differences are the character:
Body follow — 2.6 Hz, z 0.55, r 1.8. The torso trails the logical position. Lateness at this frequency reads as weight.
Heading — 2.8 Hz, r 2.2. Turns overshoot the direction of travel and swing back.
Lean — 2.4 Hz, z 0.4, chasing acceleration rather than position, so it tips into a start and rocks when you stop.
Head — 2.4 Hz, r −1.8. Turns the wrong way first, then leads the body into the corner.
Bob — 3.8 Hz, z 0.45. Not driven by a target at all; each footfall kicks its velocity directly.
Squash & stretch — 5.0 Hz, z 0.35. A jump adds an impulse of 6.0; a landing subtracts one scaled by impact speed.
Danglies — 1.9 Hz, z 0.35. Antennae and tails are chains of springs chasing a rest pose derived from the parent transform, then distance-constrained. Because they live in world space, every turn of the body excites them.
Velocity itself is sprung, at 2.0 Hz with z at 1 — no overshoot, because a creature that overshoots its own intended speed feels broken rather than lively. That shaped acceleration is what the lean channel reads.
Two things are deliberately not sprung. Gravity is crisp: the jump's vertical velocity is integrated normally, because a sprung jump arc stops obeying the arithmetic everyone can already see. And the logical position is exact, which is what gives every other channel something honest to be late against.
Impulses are the second mechanism, and they matter more than they look. Rather than move a target, they add velocity to a spring's state directly — a shove instead of a request. A foot-plant shoves the bob channel by −0.85 × step energy. The spring does the rest, and the result is a bounce whose timing comes from where the feet actually landed instead of from a curve on a timeline.
The lag is the personality. Every character difference on this page is one of these channels tuned differently, and nothing else.
Hands on
Try it
This is the real Biped class walking real ground. Change the tuning with a preset, swap the body underneath it, or slow time to a third and watch individual channels settle.
Legs
Walking with no walk cycle
There is no step animation. A foot is planted at a world position and stays there while the body walks over it.
Each foot has a home — a point in creature-local space that moves with the body. When the distance between the planted foot and its drifting home passes a threshold, that foot swings. The threshold is base + speed × speed01, which is the whole reason a slow walk takes short shuffling steps and a run opens the stride: one number, scaled by how fast you are going.
The swing goes along an arc to a predicted landing — where the home will be, extrapolated along the velocity and capped so a foot cannot reach implausibly far ahead. Knee and ankle come from analytic two-bone IK, with a per-leg direction hint deciding which way the joint bends. Then the drawn foot chases the state machine's foot through one more second-order system, so every plant lands with a small settle.
Gait is not choreography, it is a rota. Every leg is assigned a group number, and a leg may only swing while the other groups are standing. Two alternating groups on a biped is a walk. On the quadruped the groups are set diagonally — front-left with back-right — and a trot appears without anything in the code mentioning a trot. The crab's six legs are grouped as alternating tripods: left-front, left-back and right-middle move together.
Push the speed and the rule relaxes. Above speed01 > 0.5, a leg may begin its swing once the standing group is already 60% through its own — so the groups overlap, and a flight phase with every foot off the ground appears in the schedule. Nobody implemented running. It is a consequence of two thresholds.
A step is a decision, not a recording. That is why the same leg code serves two legs, four legs and six.
One number
The crab walks sideways for free
The crab is the cleanest evidence that none of this is authored per creature.
It has its own body plan — six legs, a wider stance, a lower bob scale of 0.45 because a crab shouldn't heave like a bird. But its sideways walk is not a sideways walking behaviour. It is a heading offset of π/2: one constant that rotates where the body aims relative to where it travels. Same springs, same step machine, same rota. It simply points across its own path, and everything downstream carries on as normal.
Switch to Scuttle in the demo above and it is the same code you were just watching walk forwards.
Personality
A character is a set of numbers
A creature here is a body plan — some primitives, a few leg positions, a group assignment, and two scale factors for how much it bobs and squashes — plus a tuning for each channel. There is no behaviour layer.
The Robotic preset sets every damping ratio to 1 and every initial response to 1. Nothing overshoots; nothing anticipates; nothing is ever late. The lean and squash amounts drop to 0.15. The bird keeps walking, keeps stepping, keeps turning — and goes completely hollow. It is a working appliance.
Cartoon is the same body and the same code with the numbers moved the other way: r at 2.5 on the body and 3.0 on the heading, so it lunges out of every move; the head at −3.0, so it winds up hard backwards before turning; damping down at 0.28 on squash, so landings ring. Nothing was added.
The gap between an appliance and a performer, in this engine, is about a dozen floating-point numbers.
The bill
What this approach costs
Solving motion rather than storing it buys generality and gives up control. Some of that is a fair trade, some of it is just the cost.
The visible body is never where the logic is. That is the whole design, and it means you cannot place the drawn creature exactly. If a shot needed the head at a precise point on a precise frame, this engine cannot promise it.
The ground is flat. Feet are planted by a distance threshold, not by contact — nothing samples a terrain height or tests a collision. On level ground it is indistinguishable from real footing, and on a slope it would be wrong immediately.
The rota is authored. The rhythm emerges — trot, tripod, flight phase, all of it — but which leg alternates with which is a group number set by hand per body plan. A new creature needs somebody to decide its groups.
Underdamping is a taste dial, not a correctness dial. A channel below z 1 will ring, and a rapid change of direction can look sloppy rather than lively. There is no setting that is right; there is only a setting that suits the creature.
Gravity is inconsistent on purpose. Every other quantity in the creature is sprung and the jump is not, because the alternative looked wrong. It is a deliberate exception, and it is the seam where the method's uniformity stops.
The method itself is not mine: it is t3ssel8r's second-order system from Giving Personality to Procedural Animations Using Math, and the reparameterisation into f, z and r is what makes it something you can tune by feel. The integrator is semi-implicit Euler, hardened two ways — k₂ clamped when the frames run slow, pole-zero matching when the system runs fast relative to the frame — so a stiff spring cannot explode on a bad frame.
Nothing here stores a movement, so nothing here can reproduce one exactly. In exchange, every body given to it can walk, turn, jump and land on the first try, in any temperament.