godot-characterbody-2d

安装量: 62
排名: #12047

安装

npx skills add https://github.com/thedivergentai/gd-agentic-skills --skill godot-characterbody-2d
CharacterBody2D Implementation
Expert guidance for player-controlled 2D movement using Godot's physics system.
NEVER Do
NEVER multiply velocity by delta when using
move_and_slide()
move_and_slide()
already accounts for delta time. Multiplying causes slow, frame-dependent movement.
NEVER forget to check
is_on_floor()
before jump
— Allows mid-air jumps without double-jump mechanic.
NEVER use
velocity.x = direction * SPEED
without friction
— Character slides infinitely without friction in else branch. Use
move_toward(velocity.x, 0, FRICTION * delta)
.
NEVER set
velocity.y
to exact value when falling
— Overwrites gravity accumulation. Use
velocity.y += gravity * delta
instead of
velocity.y = gravity
.
NEVER use floor_snap_length > 16px
— Large snap values cause "sticking" to slopes and walls.
Available Scripts
MANDATORY
Read the appropriate script before implementing the corresponding pattern.
expert_physics_2d.gd
Complete platformer movement with coyote time, jump buffering, smooth acceleration/friction, and sub-pixel stabilization. Uses move_toward for precise control.
dash_controller.gd
Frame-perfect dash with I-frames, cooldown, and momentum preservation.
wall_jump_controller.gd
Wall slide, cling, and directional wall jump with auto-correction.
Do First
Read expert_physics_2d.gd for platformer foundation before adding dash/wall-jump. When to Use CharacterBody2D Use CharacterBody2D For: Player characters (platformer, top-down, side-scroller) NPCs with custom movement logic Enemies with non-physics-based movement Use RigidBody2D For: Physics-driven objects (rolling boulders, vehicles) Objects affected by forces and impulses Platformer Movement Pattern Basic Platformer Controller extends CharacterBody2D const SPEED := 300.0 const JUMP_VELOCITY := - 400.0

Get the gravity from the project settings

var gravity : int = ProjectSettings . get_setting ( "physics/2d/default_gravity" ) func _physics_process ( delta : float ) -> void :

Apply gravity

if not is_on_floor ( ) : velocity . y += gravity * delta

Handle jump

if Input . is_action_just_pressed ( "jump" ) and is_on_floor ( ) : velocity . y = JUMP_VELOCITY

Get input direction

var direction := Input . get_axis ( "move_left" , "move_right" )

Apply movement

if direction : velocity . x = direction * SPEED else : velocity . x = move_toward ( velocity . x , 0 , SPEED ) move_and_slide ( ) Advanced Platformer with Coyote Time & Jump Buffer extends CharacterBody2D const SPEED := 300.0 const JUMP_VELOCITY := - 400.0 const ACCELERATION := 1500.0 const FRICTION := 1200.0 const AIR_RESISTANCE := 200.0

Coyote time: grace period after leaving platform

const COYOTE_TIME := 0.1 var coyote_timer := 0.0

Jump buffering: remember jump input slightly before landing

const JUMP_BUFFER_TIME := 0.1 var jump_buffer_timer := 0.0 var gravity : int = ProjectSettings . get_setting ( "physics/2d/default_gravity" ) func _physics_process ( delta : float ) -> void :

Gravity

if not is_on_floor ( ) : velocity . y += gravity * delta coyote_timer -= delta else : coyote_timer = COYOTE_TIME

Jump buffering

if Input . is_action_just_pressed ( "jump" ) : jump_buffer_timer = JUMP_BUFFER_TIME else : jump_buffer_timer -= delta

Jump (with coyote time and buffer)

if jump_buffer_timer

0 and coyote_timer

0 : velocity . y = JUMP_VELOCITY jump_buffer_timer = 0 coyote_timer = 0

Variable jump height

if Input . is_action_just_released ( "jump" ) and velocity . y < 0 : velocity . y *= 0.5

Movement with acceleration/friction

var direction := Input . get_axis ( "move_left" , "move_right" ) if direction : velocity . x = move_toward ( velocity . x , direction * SPEED , ACCELERATION * delta ) else : var friction_value := FRICTION if is_on_floor ( ) else AIR_RESISTANCE velocity . x = move_toward ( velocity . x , 0 , friction_value * delta ) move_and_slide ( ) Top-Down Movement Pattern 8-Directional Top-Down extends CharacterBody2D const SPEED := 200.0 const ACCELERATION := 1500.0 const FRICTION := 1000.0 func _physics_process ( delta : float ) -> void :

Get input direction (normalized for diagonal movement)

var input_vector := Input . get_vector ( "move_left" , "move_right" , "move_up" , "move_down" ) if input_vector != Vector2 . ZERO :

Accelerate toward target velocity

velocity

velocity . move_toward ( input_vector * SPEED , ACCELERATION * delta ) else :

Apply friction

velocity

velocity . move_toward ( Vector2 . ZERO , FRICTION * delta ) move_and_slide ( ) Top-Down with Rotation (Tank Controls) extends CharacterBody2D const SPEED := 200.0 const ROTATION_SPEED := 3.0 func _physics_process ( delta : float ) -> void :

Rotation

var rotate_direction := Input . get_axis ( "rotate_left" , "rotate_right" ) rotation += rotate_direction * ROTATION_SPEED * delta

Forward/backward movement

var move_direction := Input . get_axis ( "move_backward" , "move_forward" ) velocity = transform . x * move_direction * SPEED move_and_slide ( ) Collision Handling Detecting Floor/Walls/Ceiling func _physics_process ( delta : float ) -> void : move_and_slide ( ) if is_on_floor ( ) : print ( "Standing on ground" ) if is_on_wall ( ) : print ( "Touching wall" ) if is_on_ceiling ( ) : print ( "Hitting ceiling" ) Get Collision Information func _physics_process ( delta : float ) -> void : move_and_slide ( )

Process each collision

for i in get_slide_collision_count ( ) : var collision := get_slide_collision ( i ) print ( "Collided with: " , collision . get_collider ( ) . name ) print ( "Collision normal: " , collision . get_normal ( ) )

Example: bounce off walls

if collision . get_collider ( ) . is_in_group ( "bouncy" ) : velocity = velocity . bounce ( collision . get_normal ( ) ) One-Way Platforms extends CharacterBody2D func _physics_process ( delta : float ) -> void :

Allow falling through platforms by pressing down

if Input . is_action_pressed ( "move_down" ) and is_on_floor ( ) : position . y += 1

Move slightly down to pass through

velocity . y += gravity * delta move_and_slide ( ) Movement States with State Machine extends CharacterBody2D enum State { IDLE , RUNNING , JUMPING , FALLING , DASHING } var current_state := State . IDLE var dash_velocity := Vector2 . ZERO const DASH_SPEED := 600.0 const DASH_DURATION := 0.2 var dash_timer := 0.0 func _physics_process ( delta : float ) -> void : match current_state : State . IDLE : _state_idle ( delta ) State . RUNNING : _state_running ( delta ) State . JUMPING : _state_jumping ( delta ) State . FALLING : _state_falling ( delta ) State . DASHING : _state_dashing ( delta ) func _state_idle ( delta : float ) -> void : velocity . x = move_toward ( velocity . x , 0 , FRICTION * delta ) if Input . is_action_pressed ( "move_left" ) or Input . is_action_pressed ( "move_right" ) : current_state = State . RUNNING elif Input . is_action_just_pressed ( "jump" ) : current_state = State . JUMPING move_and_slide ( ) func _state_dashing ( delta : float ) -> void : dash_timer -= delta velocity = dash_velocity if dash_timer <= 0 : current_state = State . IDLE move_and_slide ( ) Best Practices 1. Use Constants for Tuning

✅ Good - easy to tweak

const SPEED := 300.0 const JUMP_VELOCITY := - 400.0

❌ Bad - magic numbers

velocity . x = 300 velocity . y = - 400 2. Use @export for Designer Control @ export var speed : float = 300.0 @ export var jump_velocity : float = - 400.0 @ export_range ( 0 , 2000 ) var acceleration : float = 1500.0 3. Separate Movement from Animation func _physics_process ( delta : float ) -> void : _handle_movement ( delta ) _handle_animation ( ) move_and_slide ( ) func _handle_movement ( delta : float ) -> void :

Movement logic only

pass func _handle_animation ( ) -> void :

Animation state changes only

if velocity . x

0 : $AnimatedSprite2D . flip_h = false elif velocity . x < 0 : $AnimatedSprite2D . flip_h = true 4. Use Floor Detection Parameters func _ready ( ) -> void :

Set floor parameters

floor_max_angle

deg_to_rad ( 45 )

Max slope angle

floor_snap_length

8.0

Distance to snap to floor

motion_mode

MOTION_MODE_GROUNDED

Vs MOTION_MODE_FLOATING

Common Gotchas
Issue
Character slides on slopes

Solution: Increase friction

const
FRICTION
:=
1200.0
Issue
Character stutters on moving platforms

Solution: Enable platform snap

func _physics_process ( delta : float ) -> void : move_and_slide ( )

Snap to platform velocity

if
is_on_floor
(
)
:
var
floor_velocity
:=
get_platform_velocity
(
)
velocity
+=
floor_velocity
Issue
Double jump exploit

Solution: Track if jump was used

var can_jump := true func _physics_process ( delta : float ) -> void : if is_on_floor ( ) : can_jump = true if Input . is_action_just_pressed ( "jump" ) and can_jump : velocity . y = JUMP_VELOCITY can_jump = false Reference Godot Docs: CharacterBody2D Godot Docs: Using CharacterBody2D Related Master Skill: godot-master

返回排行榜