Quick answer: Raise Step Offset above your tallest step (default 0.3 m, try 0.5). Confirm Slope Limit covers the stair angle. For smooth stair feel, hide an inclined ramp collider over visual stair geometry — the character glides up the ramp while players see steps.
Here is how to fix Unity CharacterController catching on stairs as if it forgot how to climb. The character runs flat on smooth ground but stops dead at every stair edge. Or it climbs but bumps visibly with each step. The fix is part Step Offset configuration, part level design trickery to make stairs traversable.
The Symptom
The character runs into a flight of stairs and stops. Or it climbs but stutters with each step, breaking camera smoothness. Sometimes only certain stairs cause issues; others work fine.
What Causes This
Step Offset too small. Default 0.3 m handles a 10-inch step. Modern level art often uses larger steps for fantasy/sci-fi feel.
Slope Limit too tight. The angle of the imaginary ramp through the stairs may exceed the limit. CharacterController treats steeper as wall; cannot climb.
Capsule radius catches lip. A wide capsule clips the stair lip and refuses the step-up.
Skin Width too small. Skin Width below 0.08 m can cause edge clipping; raise to 0.1 m for smoother step traversal.
The Fix
Step 1: Raise Step Offset.
// Inspector or code
controller.stepOffset = 0.5f; // up to 0.6 for tall steps
controller.slopeLimit = 50f; // up to 55 for steeper stair runs
controller.skinWidth = 0.1f;
Step Offset must be less than capsule height minus skin width or it gets clamped silently.
Step 2: Use a stair ramp collider. The standard solution: keep your stair visual mesh, but place an invisible inclined plane collider over it at the slope angle. Set the visual stair mesh’s collider to disabled or move it to a layer the character does not collide with. The character glides up the ramp; players see steps.
// Hierarchy:
StairMesh (visual mesh, no collider)
StairRampCollider (BoxCollider rotated to ramp angle)
Step 3: Tune capsule radius. A capsule radius of 0.3 m is typical for a humanoid. If your character is wider, the radius can catch tile edges; consider keeping the visible width while shrinking the collision radius slightly (0.25 m) to ease step traversal.
Step 4: Detect ground manually for cinematic stairs.
void SnapToGround()
{
if (Physics.Raycast(transform.position, Vector3.down, out RaycastHit hit, 2f))
{
if (hit.distance < 1.1f)
{
var snap = (hit.distance - 1.0f); // keep feet 1m from camera
controller.Move(Vector3.down * snap);
}
}
}
Call after movement to keep the character glued to varying ground heights, smoothing minor stair bumps.
Step 5: For steep stairs, replace with multiple smaller ramps. Visually segmented steep stairs can use a series of ramp segments. Each ramp respects Slope Limit; transitions between them are smooth.
Common Pitfalls
Trying to use CharacterController for traversing very tall obstacles. CharacterController is designed for human-scale traversal; for climbing or vaulting, custom physics or animation root motion is more appropriate.
Using Rigidbody plus CharacterController on the same actor. They fight. Pick one.
“Step Offset for tall steps. Ramp colliders for smooth feel. Two simple tools handle every stair.”
Related Issues
For NavMesh edge issues, see NavMeshAgent Stuck on Edge. For Rigidbody falling, see Rigidbody Falling Through Floor.
Step Offset wide enough. Ramp under stairs. The character glides up.