Quick answer: Set floor_snap_length to e.g. 8 (pixels). floor_max_angle to 45 deg. Don’t manually reset velocity.y; let move_and_slide handle landing. Up direction = Vector2.UP.
Player walks down a slope and bounces every frame. CharacterBody2D becomes airborne briefly between physics ticks; gravity engages; lands again.
The Symptom
Visible vertical hops while moving down slopes. Sometimes the floor detection toggles in is_on_floor() reads.
The Fix
extends CharacterBody2D
@export var SPEED := 200.0
@export var GRAVITY := 980.0
func _ready() -> void:
floor_snap_length = 8.0 # keep grounded over slopes
floor_max_angle = deg_to_rad(45)
floor_constant_speed = true
up_direction = Vector2.UP
func _physics_process(delta: float) -> void:
if not is_on_floor():
velocity.y += GRAVITY * delta
var input := Input.get_axis("move_left", "move_right")
velocity.x = input * SPEED
move_and_slide()
floor_snap_length lets the body ride the slope without becoming airborne. floor_constant_speed keeps horizontal speed unchanged on slopes.
Verifying
Walk down a slope. Smooth movement. is_on_floor stays true. Without snap: visible bounce.
“Snap length. Constant speed. Slopes glide.”
Related Issues
For CharacterBody3D stairs, see 3D stairs. For physics interpolation, see interpolation.
Snap. Constant. Slopes work.