mcpField
G
godot-2d-movement

godot-2d-movement

github.com/gamedev-skills开发5.4k6.8k 次安装1 天前更新
代码仓库

关于 godot-2d-movement

面向 Godot 4.7 的技能,介绍如何用 CharacterBody2D 编写灵敏的 2D 角色移动。内容涵盖平台跳跃和俯视角控制器、碰撞反馈及常见移动问题。

主要功能

  1. 01CharacterBody2D 移动设置
  2. 02平台跳跃的重力与跳跃
  3. 03俯视角八方向移动
  4. 04滑动碰撞与地面检测
  5. 05土狼时间模式
  6. 06Godot 4.x 移动常见问题

适用场景

  1. 01实现平台跳跃角色控制器
  2. 02创建俯视角移动角色
  3. 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。

核心工作流

  1. 使用 CharacterBody2D,并将 CollisionShape2D 设为其子节点。它由脚本驱动:不会自行下落或响应力的作用。
  2. 设置 velocity 属性,然后调用 move_and_slide()(4.x 中不带参数)。 该方法读取 velocity,移动物体,使其沿表面滑动,并更新 velocity,以反映实际发生的移动。
  3. 在 _physics_process(delta) 中执行——move_and_slide() 会在内部使用物理步长的 delta,因此不要自行将 velocity 乘以 delta。
  4. 平台跳跃游戏: 每个物理帧将重力加到 velocity.y 上;当 is_on_floor() 返回 true 时,将 velocity.y 设为负值以跳跃。
  5. 俯视角游戏: 根据输入生成方向并乘以速度;设置 motion_mode = MOTION_MODE_FLOATING,这样就不会区分“地面/墙壁”。
  6. 调用后读取结果,使用 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