Quick answer: Set floor_snap_length to roughly your largest step rise (e.g., 12 px). Disable snap when jumping (velocity.y < 0). Use chamfered step collision shapes.
A platformer with stairs: player walks up cleanly. Press jump and they barely lift off — the snap immediately pulls them back. Or the player walks off a small ledge and the snap teleports them down to the next surface, eliminating the fall.
Snap Behavior
floor_snap_length keeps CharacterBody2D “glued” to slopes when walking. The engine snap-tests this distance below the body each move_and_slide and pulls down if it finds floor. Set too large, it snaps through gaps; set too small, it loses contact on slopes.
The Fix Pattern
extends CharacterBody2D
const JUMP_VELOCITY = -400
const NORMAL_SNAP = 12.0 # px, slightly more than max step height
func _physics_process(delta):
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = JUMP_VELOCITY
floor_snap_length = 0 # disable while jumping
if velocity.y > 0: # falling or grounded
floor_snap_length = NORMAL_SNAP
move_and_slide()
Snap is high (12 px) when grounded or falling; zero during the jump rise so the upward velocity isn’t eaten. After apex, falling resumes the snap and the character lands cleanly.
Step Geometry
Sharp 90-degree step rises read as walls when their height exceeds floor_max_angle’s effective range. Chamfer the step edges in collision: a 45-degree slope from step top to next-step top. Visually the steps look square; physically the character flows up.
Auto-Step Helper
Some games use an explicit step-up: when the character’s hitbox detects a small wall in front, momentarily raise their Y by the step height to mount the step. More complex than snap but predictable on stair geometry.
Verifying
Walk up stairs: smooth, no air-time between steps. Press jump from any step: full jump arc, no snap-down. Walk off a small ledge: appropriate fall, no teleport.
“Snap on for ground; off for jumps. Tune length to your tallest step. The pattern is two lines.”
For tight platformers, snap is on by default but turn off during all upward velocity — jumps and impulses both feel better.