Paws that stay planted: two-bone IK in Molang for the Doggoyle
How the Doggoyle in the LLS Magic Pack keeps its paws on the ground at a walk, trot and gallop: a stride clock from ground speed, footfalls planned on the floor, and inverse kinematics solved every frame in Bedrock's Molang.
Most Minecraft mobs walk by swinging their legs back and forth on a sine wave. It’s cheap and it reads fine on a cow, but the feet slide: a leg swings at one speed, the body moves at another, and the paws skate over the ground. On a big, heavy stone hound with long clawed paws, that skating is the first thing you notice.
The Doggoyle, the hoggoyles’ guard dog in the Magic Pack, does it the other way round. Each paw’s position is planned on the ground first, and the leg bends to put it there. That’s inverse kinematics, and on Bedrock it has to run in Molang, the expression language in the resource pack, every frame, on the player’s device.
Why the leg has to be solved
Animating a leg normally means setting joint angles: shoulder this much, elbow that much. The paw ends up wherever those angles put it. Inverse kinematics turns that around: you say where the paw goes, and solve for the angles.
A dog’s foreleg and hind leg are each two long bones with a joint between them, which is the classic two-bone case:
- Foreleg: the shoulder at the top, the elbow behind it, the forearm angling forward to the wrist.
- Hind leg: the hip, the stifle forward, the tibia back to the hock, then a near-vertical metatarsus to the paw.
Given the root (shoulder or hip), the target (wrist or hock), and the two bone lengths, the bend has exactly one answer on each side. Which side it bends is what makes it a dog and not a bird: elbows fold back, stifles fold forward.
The solve itself is two Molang functions: math.atan2 for the direction from root to
target, and math.acos with the law of cosines for how far each joint bends to make up the
distance. Bedrock’s Molang works in degrees, which helps; the bone rotation is then the rest
angle, minus the parent’s pitch, minus the solved angle. Four legs, four solves, every frame.
Step 1: a stride clock that knows how fast it’s going
Before you can plan footfalls you need to know where in its stride the dog is. The obvious
input is q.modified_distance_moved, the limb-swing counter vanilla mobs use. It isn’t in
blocks: it runs at roughly four times the distance and is capped. A stride timed off it
comes out wrong at every speed. (That one’s in an earlier post about silent Bedrock bugs.)
So the Doggoyle’s clock runs on q.ground_speed, real speed over the ground, integrated
into a stride phase. The counter is only a fallback. The gait comes from speed too:
| Gait | Footfall pattern |
|---|---|
| Walk | Four beats: left hind, left fore, right hind, right fore, a quarter stride apart |
| Trot | Diagonal pairs: left hind with right fore, then the other pair half a stride later |
| Gallop | A dog’s rotary gallop: left hind, right hind, right fore, left fore, round the body |
Changing gait moves every leg forward through its cycle to the new timing, never back, so there’s no backwards-twitching leg at a gait change.
Step 2: plan the paw on the ground
Each leg has a phase in the stride. Part of the stride it’s down (the stance), the rest it’s up (the swing).
- Down: the paw sweeps backwards in a straight line, at exactly the speed the ground is moving under the dog. The sweep is the stride length times the fraction of the stride the paw is down. Match those and a planted paw doesn’t move relative to the ground. That’s the whole point.
- Up: the paw travels forward on a Hermite curve whose speeds at each end match the stance, so there’s no jolt at lift-off or touch-down.
The paw also tilts: the heel peels up at the end of the stance while the toes stay down, and it flips back in the swing. These paws are long (the claws reach seven units ahead of the wrist), so a folded paw needs the wrist lifted to clear the floor. The lift is calculated from the fold, not guessed, plus a little clearance.
Then the IK takes the wrist and hock targets and bends the legs to reach them.
I checked it offline with the same maths the Molang runs, at every gait: a planted paw moves less than 0.4 units over a stance.
What went wrong, and how each was caught
Every one of these was found by a numeric check (a kink in a joint curve, a paw below the floor) rather than by eye. Watching an animation at full speed hides a lot.
A hard reach limit kinks the elbow
At full gallop a paw’s target can be further away than the leg can reach. The obvious fix,
math.clamp on the distance, locks the elbow dead straight, then releases it: a visible
snap at the end of every reach.
The fix is a soft limit. Within one unit of full reach, the distance eases in exponentially instead of stopping dead:
reach = d < dmax - 1 ? d : dmax - math.exp(dmax - 1 - d)
The leg straightens smoothly and never quite locks.
A paw that folds too far, buckles twice
Long paws have an awkward property: the claw tips hang lowest at about 70 degrees of
fold. The first version peeled, folded and lifted the paw on three separate curves joined
with max(), and the fold passed 70 degrees twice per swing. So the wrist lift it needed had
two humps, and the elbow buckled twice a stride.
Now the paw’s whole flex is one smooth bump, a raised cosine: it starts as the heel peels, peaks early in the swing, and has flattened out by 85% of the swing so the paw lands flat. The fold is capped so it never passes the low point.
Lift a hind paw too high and the thigh whips
The hind paw folds much less than the forepaw. Lifted as high as the front, it put the hock right next to the hip, and near a straight line through the root the solve is hypersensitive: the thigh swung 50 degrees in two frames.
Body roll sinks one side’s paws
A trotting dog rolls, which lowers one shoulder and raises the other. With one shared root height, the paws on the low side pushed into the floor. Each leg now gets its own root height from the roll, so the low side bends more and the high side reaches.
Shoulders that swing like a door
The first model built the shoulder as one piece with the upper arm, a slab up to the withers. Every step swung the whole slab through the body like a pendulum. The shoulder and haunch are now fixed blocks on the body, with the limb tucked inside them.
Blending poses: blend where the paw goes, not the angles
The Doggoyle leaps, lands, sits, lies down, and paddles in water. The first leap blended two sets of joint angles: the running pose and the in-air pose. Blending angles produces a leg that’s longer than either, so for the first frames of every landing, the paws went 1.4 units through the floor.
Now the blend is on where the paw goes, and the one IK solves the leg every frame from that. Paw tilt works the same way: cancel the whole chain’s rotation, then add one blended world tilt, so a paw never passes through toes-straight-down while it’s low.
Chins through the floor
Sitting, lying and curling up were posed by hand, and each looked right on its own. Then the body dropped to lie down and the chin went through the ground. The rest poses are now solved against the floor (a bisection search for the height where the chin just clears), and there’s a per-frame chin guard: whatever mix of states the dog is in, the chin’s height is worked out from the body, and it never goes below the floor.
It all runs in Molang
All of this sits in the client entity’s pre_animation scripts, which run every frame before
the animations. Molang has fixed-arity functions (math.max takes exactly two arguments, and
three silently breaks the whole entity) and aborts if you read a variable before setting it, so
the order of the lines matters as much as the maths. The model, the animation and the Molang
are generated together by one script, which also runs the checks above before it writes
anything.
Meet the Doggoyle in the Magic Pack’s sulfur dungeons. Tame one with a plain golden apple; the Magic Pack guide explains how to find a dungeon.
The mod
More from the devlog
- Five Bedrock add-on bugs that fail without an error An invisible horse, legs running four times too fast, a mob that forgot how to jump, and a magic pack that broke without being touched. Five Minecraft Bedrock add-on bugs I hit building LLS Equestrian and the Magic Pack, and how to catch them.
- Making it snow on a plains farm: faking winter weather in Minecraft Bedrock Bedrock has no snow weather and decides rain-or-snow from the biome. How LLS Seasons builds a snowy day from fog, a particle and a snow carpet of its own, and the summer freeze a snow sweep caused.
- Making a gate swing in Minecraft Bedrock, when blocks can't animate Bedrock blocks can't move, and a custom block's collision has to fit inside one block. How the double-wide gates in LLS Missing Blocks fake both, and the collision tricks that keep a cow in and let a horse through.