关于 godot-2d-movement
面向 Godot 4.7 的技能,介绍如何用 CharacterBody2D 编写灵敏的 2D 角色移动。内容涵盖平台跳跃和俯视角控制器、碰撞反馈及常见移动问题。
主要功能
- 01CharacterBody2D 移动设置
- 02平台跳跃的重力与跳跃
- 03俯视角八方向移动
- 04滑动碰撞与地面检测
- 05土狼时间模式
- 06Godot 4.x 移动常见问题
适用场景
- 01实现平台跳跃角色控制器
- 02创建俯视角移动角色
- 03排查地面与碰撞问题
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ gamedev-skills/ awesome-gamedev-agent-skills --skill godot-2d-movement安装后在 Claude Code 中输入/godot-2d-movement确认已加载。
附带文件references/controller-recipes.md
详细介绍
Godot 2D 移动(4.x)
使用 CharacterBody2D 和不带参数的
move_and_slide() 构建响应灵敏的 2D 角色控制器。目标版本为 Godot 4.7。
适用场景
- 为会移动并发生碰撞的 2D 玩家角色或敌人编写脚本时:平台跳跃游戏(重力 + 跳跃)、俯视角游戏(自由八方向移动)、斜坡行走或墙面/地面检测。
move_and_slide()“没有效果”、角色穿过地面,或is_on_floor()始终返回 false 时。
不适用场景: 动态刚体、区域、射线检测、碰撞层 → godot-physics;基于图块的关卡 → godot-tilemap;完整的平台跳跃游戏模板 → platformer 类型技能;与引擎无关的手感调校 → physics-tuning。
核心工作流
- 使用
CharacterBody2D,并将CollisionShape2D设为其子节点。它由脚本驱动:不会自行下落或响应力的作用。 - 设置
velocity属性,然后调用move_and_slide()(4.x 中不带参数)。 该方法读取velocity,移动物体,使其沿表面滑动,并更新velocity,以反映实际发生的移动。 - 在
_physics_process(delta)中执行——move_and_slide()会在内部使用物理步长的 delta,因此不要自行将velocity乘以delta。 - 平台跳跃游戏: 每个物理帧将重力加到
velocity.y上;当is_on_floor()返回 true 时,将velocity.y设为负值以跳跃。 - 俯视角游戏: 根据输入生成方向并乘以速度;设置
motion_mode = MOTION_MODE_FLOATING,这样就不会区分“地面/墙壁”。 - 调用后读取结果,使用
is_on_floor()、is_on_wall()、get_wall_normal()和get_slide_collision(i)。
模式
1. 平台跳跃控制器(重力、跳跃、斜坡)
extends CharacterBody2D
@export var speed := 200.0
@export var jump_velocity := -400.0
@export var gravity := 1200.0 # pixels/sec^2 (tune to taste)
func _physics_process(delta: float) -> void:
# Apply gravity while airborne.
if not is_on_floor():
velocity.y += gravity * delta
# Jump only when grounded (Input action set in Project Settings > Input Map).
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = jump_velocity
# Horizontal input: -1, 0, or 1.
var dir := Input.get_axis("move_left", "move_right")
if dir != 0.0:
velocity.x = dir * speed
else:
velocity.x = move_toward(velocity.x, 0.0, speed) # decelerate to a stop
move_and_slide() # 4.x: no arguments; uses and updates `velocity`
2. 俯视角八方向移动
extends CharacterBody2D
@export var speed := 220.0
func _ready() -> void:
motion_mode = CharacterBody2D.MOTION_MODE_FLOATING # no floor/ceiling concept
func _physics_process(_delta: float) -> void:
# get_vector returns a normalized-ish Vector2 from four input actions.
var input := Input.get_vector("move_left", "move_right", "move_up", "move_down")
velocity = input * speed
move_and_slide()
3. 移动后读取滑动碰撞
func _physics_process(delta: float) -> void:
# ... set velocity ...
move_and_slide()
for i in get_slide_collision_count():
var c := get_slide_collision(i)
var other := c.get_collider()
if other and other.is_in_group("enemies"):
take_damage(1) # touched an enemy while moving
4. 土狼时间(离开平台边缘后仍可宽容地跳跃)
@export var coyote_time := 0.1
var _coyote := 0.0
func _physics_process(delta: float) -> void:
if not is_on_floor():
velocity.y += gravity * delta
_coyote -= delta
else:
_coyote = coyote_time
if Input.is_action_just_pressed("jump") and _coyote > 0.0:
velocity.y = jump_velocity
_coyote = 0.0
# ... horizontal input + move_and_slide() ...
常见问题
- 3.x 版本的方法签名已移除。
move_and_slide(velocity)(返回新速度)已不再使用。在 4.x 中,设置velocity属性,并调用不带参数的move_and_slide()。move_and_slide(velocity, Vector2.UP)无法解析。 - 将速度乘以 delta。
move_and_slide()已经考虑了物理步长的 delta。设置velocity = dir * speed * delta会让物体移动得非常缓慢。 - 在
_process而不是_physics_process中移动会导致移动依赖帧率且抖动。务必在_physics_process中移动。 is_on_floor()始终返回 false,可能是up_direction错误(默认值为Vector2.UP)、没有CollisionShape2D,或本帧从未调用move_and_slide()。- 穿过地面通常意味着碰撞形状缺失/尺寸为零、地面物体所在的层不在此物体的遮罩中,或你使用了
position +=移动物体,而不是通过速度和move_and_slide()移动。 - 静止时沿斜坡下滑: 保持
floor_stop_on_slope = true(默认值),并设置floor_snap_length,使物体贴附在向下的斜坡上。
参考资料
- 有关单向平台、移动平台、跳跃缓冲、可变跳跃高度和
move_and_collide()(手动碰撞响应),请阅读references/controller-recipes.md。
相关技能
godot-physics— 碰撞层/遮罩、区域、射线检测、刚体。godot-tilemap— 构建角色行走的关卡。godot-animation— 根据移动状态驱动精灵/骨骼动画。camera-systems— 跟随角色的跟随相机、死区和前瞻。platformer/input-systems— 完整的类型模板和可重新绑定的输入。
评论
支持 Markdown