Godot 4 CharacterBody2D 角色移动:输入、碰撞与八方向控制实战

Godot 4 CharacterBody2D 角色移动:输入、碰撞与八方向控制实战

刚接触 Godot 4 时,很多人会直接修改 Sprite2D.position 来移动玩家。画面确实动了,但角色遇到墙体时仍会穿过去,因为精灵只负责显示,不负责物理运动。

这篇文章从一个最小的俯视角角色场景出发,使用 CharacterBody2DCollisionShape2DInput.get_vector(),完成方向输入、等速斜向移动以及滑动碰撞。最终代码可以直接作为 RPG、射击或探索类 2D 游戏的移动基础。

一、先分清三种物理主体

Godot 4 中常见的二维物理主体有三种:

  • CharacterBody2D:速度由玩家代码或 AI 决定,适合角色。
  • StaticBody2D:提供固定阻挡,适合墙壁、地面和不可移动障碍。
  • RigidBody2D:主要由重力、碰撞与外力推动,适合箱子等物理对象。

关键不在于对象看起来会不会动,而在于"谁决定它如何运动"。玩家角色需要稳定、可预测的输入响应,因此这里选择 CharacterBody2D

二、搭建玩家场景

新建一个二维场景,将根节点设为 CharacterBody2D,命名为 Player。添加两个子节点:

text 复制代码
Player (CharacterBody2D)
├── AnimatedSprite2D
└── CollisionShape2D

AnimatedSprite2D 负责画面,CollisionShape2D 负责物理轮廓。两者应当分离:头发、武器和披风等装饰像素通常不该参与阻挡,否则玩家会觉得"明明没碰到墙却被卡住"。

CollisionShape2DShape 属性中创建矩形、圆形或胶囊形状,优先覆盖角色的主体区域。俯视角角色没有明确的地面方向,可以把 CharacterBody2DMotion Mode 设为 Floating

三、配置输入动作

打开 Project → Project Settings → Input Map,建立四个动作:

动作名 推荐按键
move_left A、左方向键
move_right D、右方向键
move_up W、上方向键
move_down S、下方向键

代码只依赖动作名,不直接依赖某个键。以后接入手柄或允许玩家改键时,不必重写移动逻辑。

四、编写八方向移动代码

Player 创建并附加 player_controller.gd

gdscript 复制代码
extends CharacterBody2D

@export var speed: float = 240.0

func _physics_process(_delta: float) -> void:
    var input_direction := Input.get_vector(
        "move_left",
        "move_right",
        "move_up",
        "move_down"
    )

    velocity = input_direction * speed
    move_and_slide()

这段代码只有三个关键步骤:

  1. Input.get_vector() 把四个动作合成为一个 Vector2
  2. 方向向量乘以 speed,得到角色速度。
  3. move_and_slide() 提交当前物理帧的速度并处理滑动碰撞。

不要再额外写 position += velocity * deltaCharacterBody2D 的运动应交给 move_and_slide(),否则可能避开预期的碰撞处理。

五、为什么斜着走不会更快

如果分别判断四个按键,再把 X、Y 速度都设为 speed,角色斜向移动时的合速度会大于水平速度。Input.get_vector() 会把最终向量长度限制在 1 以内,因此右下方向大约是 (0.707, 0.707),乘以速度后仍保持统一的最大移动速度。

这也是它比手工堆叠四个 if 更适合八方向控制的原因。

六、添加可碰撞的障碍

在测试场景中添加 StaticBody2D,并给它添加:

text 复制代码
Wall (StaticBody2D)
├── Sprite2D
└── CollisionShape2D

运行后让玩家斜着撞向墙角。正确结果是:

  • 角色不会穿过墙体;
  • 仍有切向速度时,角色会沿墙滑动;
  • 松开输入后,角色立即停止。

如果角色直接穿墙,依次检查:

  1. 玩家和墙体是否都有可用的 CollisionShape2D
  2. Shape 是否为空;
  3. 玩家与墙体的 Collision Layer 和 Mask 是否互相匹配;
  4. 是否错误地手动修改了 position
  5. move_and_slide() 是否在 _physics_process() 中执行。

七、加入平滑加速与减速

即时停止适合强调精准操作的游戏。如果希望移动更柔和,可以让速度逐步接近目标值:

gdscript 复制代码
extends CharacterBody2D

@export var max_speed: float = 240.0
@export var acceleration: float = 1200.0
@export var deceleration: float = 1600.0

func _physics_process(delta: float) -> void:
    var input_direction := Input.get_vector(
        "move_left",
        "move_right",
        "move_up",
        "move_down"
    )

    var target_velocity := input_direction * max_speed
    var rate := acceleration if not input_direction.is_zero_approx() else deceleration

    velocity.x = move_toward(velocity.x, target_velocity.x, rate * delta)
    velocity.y = move_toward(velocity.y, target_velocity.y, rate * delta)
    move_and_slide()

move_toward() 按固定变化率逼近目标速度,delta 用来抵消帧率差异。加速度和减速度分开后,可以做出"起步柔和、松手迅速"的手感。

八、常见错误

错误一:用 Sprite2D 当角色根节点

它可以显示和移动,但不会自动获得角色碰撞运动能力。需要把 CharacterBody2D 作为物理主体。

错误二:碰撞轮廓完全包住装饰像素

过大的形状容易让角色在狭窄通道和墙角处被卡住。物理轮廓应服务于玩法手感,而不是逐像素描边。

错误三:一个物理帧多次调用 move_and_slide()

先计算完整速度,再调用一次即可。把不同方向拆成多次移动会让碰撞结果难以预测。

错误四:把 velocity 再乘一次 delta

velocity 的单位是每秒像素数,move_and_slide() 会按物理步处理。只有加速度的变化量需要乘 delta

九、知识主线与参考

本文的节点选型、碰撞轮廓、Floating 运动模式和物理移动方法,来自《大鹏 Godot 4 游戏开发入门》第 5 章中"配置可移动物理角色"与"编写物理角色移动代码"两节。文章把这些知识整理成一个可独立复现的俯视角控制器,没有把同题搜索结果当作技术事实。

十、完整验收清单

  • 单独按 W、A、S、D 时方向正确。
  • 同时按两个方向时速度没有变快。
  • 松开输入后按预期立即停止或平滑减速。
  • 碰到墙体不会穿透。
  • 斜撞墙体时可以沿墙滑动。
  • 调整窗口刷新率后,移动速度基本一致。

总结

完成这些检查后,一个可复用的 Godot 4 二维角色移动底座就建立好了。下一步可以把 velocity 交给 AnimatedSprite2D,让站立和移动动画随真实运动状态自动切换。

相关推荐
海带紫菜菠萝汤1 小时前
企业批量PDF翻译方案:从选型到部署的完整指南
人工智能·算法·pdf
Sammyyyyy1 小时前
如何利用本地技术栈构建 0 成本 AI SaaS 雏形
开发语言·人工智能·python·ai·servbay
炎火星1 小时前
电商运营做直播实时切片,有哪些 AI 工具可以选择
人工智能
LuminWave1 小时前
资本扎堆灵巧手赛道,数据基建成为规模化落地关键变量
大数据·人工智能·具身智能·灵巧手·tof相机
林小卫很行1 小时前
WorkBuddy 入门2:下载、安装、认识主界面
人工智能·云计算·腾讯云·知识管理·obsidian
AAIshangyanxiu1 小时前
Python 机器学习与深度学习气象水文海洋全域应用技术体系:地学时空数据 AI 建模、数值模式后处理、气象海洋水文智能预测与数据处理
人工智能·python·机器学习·水文气象·气象预测·气象海洋
CoderLiu1 小时前
Agent 工程的下一层:为什么「把流程写成图」还不够,还需要 Graph Engineering
前端·人工智能·后端
饼饼学习空间智能1 小时前
Kimi K3发布后,为什么数字孪生与物理AI底座更重要?从3D智能到具身智能落地
人工智能·深度学习·3d
中微极客1 小时前
边缘AI实战:TinyML模型量化与部署全解析(TensorFlow 2.18.0 + ESP32)
人工智能·python·tensorflow