Movement in a Metroidvania is the thing the player does ten thousand times. It gets judged harder than anything else in the game, and almost entirely unconsciously.

The state space

Idle, jumping, mid-air, falling, landing — plus running and attacking layered across them. Handled as discrete states with hard cuts between them, the character reads as robotic: the hitch at each boundary is small, but it’s felt on every single jump.

Built as a 2D blendspace instead, the transitions blend on velocity rather than switching on it. The character settles into a fall rather than snapping into one.

Keeping animation in sync

The harder half. An attack that fires before its animation reads as unresponsive; one that fires after reads as laggy. Neither is a bug you can find in a log — you only find it by playing.

Running, jumping, and attacking all had to stay locked to their animation timing while still blending directionally, which meant the animation state machine and the movement state had to agree on what the character was doing at every frame rather than each keeping its own idea.

What I’d do differently

The blendspace grew organically as states were added, and by the end it carried more transitions than it needed. Rebuilding it once the full move set was known — rather than extending it each time — would have left something simpler to reason about.