从零开始的 Godot 之旅 — EP6:更优雅地实现角色场景

从零开始的 Godot 之旅 --- EP6:更优雅地实现角色场景

在上一节里,我们通过直接修改 position 来让角色上下左右移动,虽然简单直观,但随着需求复杂(加入碰撞、斜坡、速度控制、暂停等),直接操作坐标就会显得"原始"。

这一节我们换一种官方推荐的方式:使用更专业的节点 CharacterBody2D 来驱动角色运动,并将角色抽取成一个可复用的独立场景。这样后面不论是玩家还是敌人,都可以共享一套更规范的结构。

一、为什么要换成 CharacterBody2D?

简单总结几点:

  1. 内置物理与碰撞:自动与 TileMap、CollisionShape2D 等协作,不用手动处理"卡墙"问题。
  2. velocity 语义明确:后续加加速度、阻力、受击击退等更自然。
  3. 自带辅助方法:move_and_slide()is_on_floor() 等让常见逻辑极简。
  4. 更符合后续扩展:状态机、动画、技能系统都围绕"速度/方向"构建,比直接改 position 更统一。

当然,如果只是一个临时的演示,也可以继续用 Node2D + 直接改坐标;但只要项目要继续发展,尽早切换到 CharacterBody2D 是值得的。

二、创建节点与基础展示

在使用新节点类型前,可以先把之前的旧角色节点隐藏,避免视图里混乱:

然后在 Node2D(主场景根)下新建节点,选择 CharacterBody2D

Godot 4 中,CharacterBody2D 是核心的 2D 角色物理节点,继承自 PhysicsBody2D,专为"玩家""敌人"这种可控或自动移动的对象设计。

为它添加一个 Sprite2D 子节点用于显示贴图,依旧是把图片拖到 Texture 属性:

三、编写脚本:输入到移动

右键 CharacterBody2D,添加脚本: 命名为:player_new.gd,示例代码如下:

ini 复制代码
extends CharacterBody2D

# 可在检查器里调整的移动速度
@export var speed: float = 100.0

# 当前输入方向向量(单位化前的原始输入)
var move_direction: Vector2 = Vector2.ZERO

func _physics_process(delta: float) -> void:
	 # 分别获取水平方向与垂直方向输入(已自动处理互斥与摇杆)
	 var x_axis: float = Input.get_axis("left", "right")
	 var y_axis: float = Input.get_axis("up", "down")
	 move_direction = Vector2(x_axis, y_axis)

	 velocity = move_direction * speed
	 move_and_slide()  # 内置处理碰撞与滑动

重点说明

  1. 使用 _physics_process 而不是 _process:物理相关的移动最好放在固定步长的物理帧回调里,避免帧率波动导致移动速度不一致。
  2. Input.get_axis(left, right):可读性好,自动处理同时按下的冲突,并兼容手柄摇杆。垂直方向同理。
  3. velocityCharacterBody2D 内置的速度向量,移动核心都围绕它展开。
  4. @export:将 speed 暴露到检查器,后续调数值无需改脚本。

检查器中即可看到导出的属性:

运行效果:

可以看到我们不再直接操作 position,而是通过速度与物理步驱动,这在继续扩展(碰撞、动画、受力)时更顺畅。

四、将角色封装成独立场景

为什么要单独抽成一个 player.tscn?核心目的:复用 + 隔离 + 易维护。

  1. 复用:之后在多个关卡、测试场景里可以直接实例化,不必重新搭建节点结构。
  2. 隔离:主场景保持"干净",逻辑分层清晰,防止一个场景里塞满无关节点。
  3. 易维护:角色的碰撞、动画、输入、状态机未来都可以逐步在这个独立场景里扩展。
  4. 可替换:后面如果要做"职业切换""不同皮肤",只需换一个同结构的角色场景文件。

操作过程:

  1. 选中刚创建的 CharacterBody2D 分支,选择"将分支保存为新场景":

2. 命名为 player.tscn,保存后在文件系统可见:

3. 双击打开,给根节点重命名为 Player: 4. 回到主场景,删除旧的临时角色节点:

5. 将 player.tscn 拖入或通过右键实例化到主场景。实例化后只显示根节点本身,子节点结构被折叠,对使用者更"简洁":

此时在主场景中调整 speed 的值只影响这个实例,不会修改 player.tscn 内的默认值。以后再实例化一个新的 Player,仍然是原始速度。这个机制和面向对象里"类与实例"很类似:场景文件像"类定义",拖进主场景的是"对象实例"。

五、小扩展方向(可选)

如果你想继续优化,可以考虑:

  1. 输入抽象:把输入逻辑拆到一个 InputController 脚本,便于后续支持手柄/键盘切换。
  2. 状态机:不同状态(移动、攻击、受击、死亡)管理速度与动画。
  3. 动画集成:给 Player 加 AnimatedSprite2DAnimationTree,根据 velocity 切换方向动画。
  4. 碰撞:补上 CollisionShape2D,否则后续与地图交互不完整。
  5. 数值调参:在检查器里再导出例如 accelerationfriction,实现更顺滑的移动。

这些暂时不急,我们在后续章节逐步展开。

六、本节小结

本节完成了两件重要的事情:

  1. CharacterBody2D 替代直接改坐标,实现更规范的移动逻辑。
  2. 将角色抽取为独立场景,建立"可复用 + 易扩展"的结构基础。

至此,我们已经对 Godot 的基础节点、输入和简单物理有了初步认识。下一节开始,将重开一个新工程,引入一套免费的素材,正式以"俯视角角色扮演"方向继续迭代。敬请期待。

相关推荐
AI广告侠1 天前
游戏开发者的AI革命:从灵感枯竭到效率狂飙,我的日常链路被AI重塑了 ——一个独立游戏开发者的AI工具箱实战指南
游戏·游戏开发
总有刁民想爱朕ha2 天前
Python自动化从入门到实战(23):Python打地鼠游戏开发
开发语言·python·游戏开发
小武的开发空间2 天前
Godot 城市模拟 – 003 根据不规则底面和高度,动态创建节点
godot
腾讯云云开发2 天前
CloudBase + AI 游戏开发新范式,3小时极速开发
ai编程·游戏开发·小程序·云开发
ZHOUYUANN3 天前
我用JavaScript复刻了某宝的小游戏动物大迁徙消消乐
前端·javascript·游戏开发
Brianna Home4 天前
Godot4.3开发2D游戏全记录
游戏·游戏引擎·godot·游戏程序·动画
小武的开发空间4 天前
Godot 城市模拟 - 002 根据地面四个点的坐标和高度,动态创建立方体节点
godot
gopyer5 天前
180课时吃透Go语言游戏后端开发11:Go语言中的并发编程
golang·go·游戏开发·并发编程