| name | godot-characterbody-2d |
| description | Expert patterns for CharacterBody2D including platformer movement (coyote time, jump buffering, variable jump height), top-down movement (8-way, tank controls), collision handling, one-way platforms, and state machines. Use for player characters, NPCs, or enemies. Trigger keywords: CharacterBody2D, move_and_slide, is_on_floor, coyote_time, jump_buffer, velocity, get_slide_collision, one_way_platforms, state_machine. |
CharacterBody2D Implementation
Expert CharacterBody2D feel systems — not beginner move_and_slide tutorials.
NEVER Do
- NEVER use
RigidBody2D for standard player controllers — RigidBody is for physics-simulated objects. For responsive, feel-driven player movement, always use CharacterBody2D.
- NEVER multiply
velocity by delta before move_and_slide() — move_and_slide() handles delta internally. Manual multiplication makes movement framerate-dependent.
- NEVER use
global_position updates for gameplay movement — Use velocity + move_and_slide(). Direct position hacks bypass collision, floor snap, and one-way rules.
- NEVER "fall through" one-ways by nudging
position.y — Use one-way collision shapes + layer/mask (and temporary mask disable / collide-with-areas patterns). See godot-2d-physics.
- NEVER ignore floor/wall/ceiling state right after
move_and_slide() — is_on_floor(), is_on_wall(), is_on_ceiling(), and slide collisions drive coyote, wall jump, and bonk logic.
- NEVER rely on default
floor_snap_length for fast stair-climbing — Default snapping is too small for high-velocity characters. Use custom raycast-based stair logic.
- NEVER apply gravity while
is_on_floor() is true — Constant downward force causes micro-jitter and fights floor-snap. Reset velocity.y on land.
- NEVER use
Area2D as primary ground detection — Prefer is_on_floor() / shapecasts; Areas are for triggers, not floor truth.
- NEVER forget ceiling bonk — Reset
velocity.y when is_on_ceiling() or the player floats into the ceiling until gravity wins.
- NEVER round physics positions for pixel art — Keep physics high-precision; round sprite positions in
_process only (subpixel_movement_rounding.gd).
- NEVER spam
queue_free() for hordes — Pool bullets/enemies when spawn/despawn is frequent (performance_character_pooling.gd).
When to Use CharacterBody2D
| Need | Body |
|---|
| Feel-driven player / NPC / enemy locomotion | CharacterBody2D |
| Rolling debris, ragdoll-ish props, force piles | RigidBody2D |
| Static level colliders | StaticBody2D / TileMapLayer physics |
Decision Tree → MANDATORY Scripts
Golden path: Read expert_physics_2d.gd first. Add dash/wall/jump scripts only after that controller is in place. Do not re-inline coyote/buffer/accel loops in the scene when the script already owns them.
One-Way Platforms (correct recipe)
- Author one-way on the platform collider (
CollisionShape2D one-way / TileSet physics one-way), not by teleporting the player.
- Put platforms and player on explicit collision layers/masks so drop-through can temporarily clear the platform bit (or disable collide-with) while holding down + jump — then restore next physics frames.
- Keep drop-through on the physics tick; never bypass
move_and_slide with position nudges.
- For tile one-ways, align TileSet physics layers with CharacterBody masks — see godot-tilemap-mastery + godot-2d-physics.
Expert Character Architectures
1. Wall Cling (Variable Friction)
Monitor is_on_wall() while falling; scale velocity.y by a friction factor (optionally from tile custom data) instead of a binary wall-slide bool. Prefer wall_slide_jump_refined.gd over a bespoke cling fork.
2. Animation-Driven Movement (Root Motion)
Pull AnimationTree.get_root_motion_position(), convert to 2D, assign velocity = motion / delta, then move_and_slide(). Keeps feet locked to authored clips; pair with godot-2d-animation.
3. Game-Feel Profiler (Jump Arcs)
Debug-draw historical positions + current velocity in _draw() to visualize apex, coyote, and buffer windows while tuning exports on expert_physics_2d.gd — game_feel_profiler.gd.
MANDATORY for top-down/tank recipes, moving platforms, slide-collision response, and gotcha tables: movement-recipes.md. Do NOT Load when expert_physics_2d.gd already covers your platformer scope.
Reference
Progressive disclosure: open Official Documentation links only when researching a specific API;
load Related Skills when routing work to a peer domain — do not preload the whole lattice.
Official Documentation
- Using CharacterBody2D — Canonical
move_and_slide / floor-wall-ceiling contracts; do not set position for gameplay motion.
- CharacterBody2D — API for
velocity, snap, is_on_floor / wall / ceiling, and slide-collision accessors.
- Physics introduction — Why CharacterBody vs RigidBody/StaticBody, and how layers/masks gate every contact.
- Collision shapes (2D) — Capsule/box sizing and why scaled
CollisionShape2D nodes corrupt normals and floor detect.
- 2D movement — Input axes into velocity for top-down and platformer starters before juice systems.
- Kinematic character (2D) — Classic slide/collision loop patterns that still inform custom stair and slope handling.
- Troubleshooting physics issues — One-way platforms, tunneling, and jitter diagnoses that show up in CharacterBody feel bugs.
- Ray-casting — Direct-space rays for stair snaps, ledge checks, and ground probes beyond
is_on_floor().
- KinematicCollision2D — Per-slide normals/remainders from
get_slide_collision for wall jumps and ceiling bonks.
- Physics interpolation introduction — Smooth visuals at high refresh while keeping jump/coyote logic on the physics tick.
- InputEvent — Action just-pressed timing that jump buffers and coyote windows depend on.
Related Skills
Prerequisites
- godot-project-foundations — Default gravity, physics tick rate, and 2D layer names must be set before coyote/jump feel is tunable.
- godot-gdscript-mastery — Typed
_physics_process, timers, and move_toward discipline underpin every movement script here.
- godot-2d-physics — Collision layer/mask matrices, one-way shapes, and query hygiene CharacterBody motion sits on.
- godot-input-handling — Physics-step action sampling so jump buffer / coyote windows stay frame-stable.
Complements
Downstream / consumers
- godot-genre-platformer — Genre-level platformer feel consumes coyote, buffer, slopes, and one-ways from this skill.
- godot-genre-metroidvania — Ability-gated movement (wall jump, dash) builds on the controllers defined here.
- godot-combat-system — Knockback and hitstun apply impulses through the same
velocity + slide loop.
- godot-monte-carlo-balancer — Coyote frames, jump height, dash cooldown, and air accel are balance knobs — simulate them instead of guessing.
Master
- godot-master — Library router and mirrored entry point for CharacterBody2D alongside sibling domains.