Quick answer: Clamp Blend2 input to [0, 1] at the write site. Sync animation lengths so foot-cycle blends don’t desync; or use Sync = ratio for automatic speed match.

A character’s locomotion uses Blend2 to mix walk and run based on velocity. At normal speeds it looks great. At sprint speeds the legs lock or perform impossible angles — the blend is extrapolating instead of clamping.

Blend Parameters Don’t Auto-Clamp

The Blend2 node interprets its blend_amount as a linear lerp factor between input 0 and input 1. Values within [0, 1] interpolate. Values outside extrapolate — 1.5 means “150% of the difference from input 0 toward input 1”, which doesn’t correspond to anything sensible for animation poses.

The fix is at the parameter-write site, not in the AnimationTree itself.

The Fix

@onready var tree: AnimationTree = $AnimationTree

func _process(delta):
    var speed = velocity.length()
    var blend = (speed - WALK_SPEED) / (RUN_SPEED - WALK_SPEED)
    blend = clamp(blend, 0.0, 1.0)
    tree.set("parameters/MoveBlend/blend_amount", blend)

The clamp ensures the parameter stays in valid range no matter how fast the character moves. Beyond RUN_SPEED, the blend stays pinned at 1.0 (pure run animation).

Sync Animation Cycles

If walk is 1.2 s and run is 0.8 s, the foot-down timings don’t line up. During blend, you’ll see one foot touch the ground twice while the other doesn’t at all. Options:

BlendSpace1D for Multi-Speed

For walk + jog + run with smooth transitions:

# In the BlendTree, replace Blend2 with BlendSpace1D
# Add points: -1.0=stand, 0.0=walk, 1.0=jog, 2.0=sprint
# Map velocity to blend position
var pos = remap(speed, 0, MAX_SPEED, -1.0, 2.0)
tree.set("parameters/Locomotion/blend_position", clamp(pos, -1.0, 2.0))

BlendSpace1D interpolates between the closest two points. Define cycle-matched animations for each tier and the transitions are smooth without extrapolation issues.

Debug Visualizer

Open the AnimationTree node in the editor. Activate Play; the BlendTree visualizer shows the current blend_amount as a slider position. Watch it during play to verify your parameter writes match your expectations.

Verifying

Sprint at maximum speed. The character should look like they’re running cleanly — no leg twisting or freezing. Walk slowly. The character should walk cleanly. Crossover speeds should show a smooth blend with synchronized feet.

“Blend nodes are linear interpolators, not clampers. Clamp before you write, and sync cycle lengths.”

Every parameter write into an AnimationTree should be clamped at the source — treat the AnimationTree as untrusting code.