Godot 节点系统详细介绍
Godot 里最核心的东西不是“类”,也不是“组件”,而是节点 Node。
你可以把 Godot 的节点理解成:
在前端里,一个页面是由很多 DOM 元素组成的;
在 Godot 里,一个游戏场景是由很多 Node 节点组成的。
比如一个玩家角色,可能不是一个单独对象,而是这样的结构:
Player / CharacterBody2D
├── Sprite2D
├── AnimationPlayer
├── CollisionShape2D
├── Camera2D
└── AudioStreamPlayer2D
这里的 Player 是根节点,下面挂着显示图片、播放动画、碰撞检测、摄像机、音效等子节点。
Godot 官方文档也把节点和场景放在一起讲:多个节点组成树状结构后,就可以保存成一个 Scene 场景,而场景保存后又可以像一种新的节点类型一样被复用。
一、Node 是什么
Node 是 Godot 里最基础的节点类型。
它本身不负责显示画面,也不负责物理碰撞,更不负责 UI 布局。它更像是一个“逻辑容器”。
它常用来做:
GameManager
SceneManager
AudioManager
QuestManager
InventoryManager
DataLoader
也就是说,如果你有一个东西不需要出现在画面里,只是负责管理逻辑,就可以用普通的 Node。
比如:
Main / Node
├── World / Node2D
├── UI / CanvasLayer
├── GameManager / Node
└── AudioManager / Node
这里 GameManager 不需要坐标,不需要图片,也不需要碰撞,所以用 Node 就够了。
Godot 的场景树 SceneTree 会管理这些节点的添加、删除、暂停、切换场景等行为。节点进入场景树后会触发 _enter_tree(),准备完成后会触发 _ready()。
二、节点的生命周期
你写 Godot 脚本时,经常会遇到这些函数:
func _enter_tree():
pass
func _ready():
pass
func _process(delta):
pass
func _physics_process(delta):
pass
func _exit_tree():
pass
它们和前端生命周期很像。
_enter_tree()
节点刚进入场景树时执行。
这个时候节点已经被加入树里了,但它的子节点不一定都准备好了。
一般不常用,除非你要做比较底层的初始化。
_ready()
节点和它的子节点都准备好之后执行。
这是你最常用的初始化位置。
比如:
@onready var sprite: Sprite2D = $Sprite2D
@onready var anim: AnimationPlayer = $AnimationPlayer
func _ready():
anim.play("idle")
你可以理解为 Vue 的 mounted,或者 React 组件第一次挂载完成之后的效果。
_process(delta)
每一帧执行一次。
适合处理和画面刷新相关的逻辑,比如:
相机跟随
角色朝向鼠标
UI 倒计时
非物理类动画
_physics_process(delta)
固定物理帧执行。
适合处理物理移动、碰撞、速度计算。
比如角色移动一般放这里:
func _physics_process(delta):
velocity = input_direction * speed
move_and_slide()
_exit_tree()
节点离开场景树时执行。
适合清理连接、停止计时器、释放状态。
三、节点和场景的关系
Godot 里一个 .tscn 场景文件,本质上就是一棵节点树。
比如你创建一个 Player.tscn:
Player / CharacterBody2D
├── Sprite2D
├── CollisionShape2D
└── AnimationPlayer
这个 Player.tscn 之后可以被放进主场景:
Main / Node2D
├── TileMapLayer
├── Player
├── Camera2D
└── CanvasLayer
所以你可以把场景理解成“组件”。
前端类比:
Vue / React 组件 = Godot Scene
DOM 节点 = Godot Node
组件嵌套 = 场景实例嵌套
props / state = 导出变量、资源、脚本属性
比如:
Player.tscn
Enemy.tscn
Chest.tscn
NPC.tscn
House.tscn
它们都是可以复用的场景。
四、2D 基础节点
1. Node2D
Node2D 是所有 2D 游戏对象最常见的基础节点。
它有:
position 位置
rotation 旋转
scale 缩放
z_index 绘制层级
visible 是否显示
Godot 官方文档说明,Node2D 是 2D 游戏对象的基础,所有 2D 节点,包括精灵、物理对象等,都继承自它;它适合作为父节点来统一移动、旋转、缩放子节点。
常用场景:
地图根节点
玩家根节点
敌人根节点
道具根节点
特效根节点
装饰物根节点
比如:
World / Node2D
├── Ground
├── Player
├── Enemies
├── Items
└── Decorations
如果一个东西存在于 2D 世界里,但暂时不需要碰撞、不需要物理控制,就可以先用 Node2D。
例如:
云朵
背景装饰
树叶飘落效果
普通装饰物容器
2. Sprite2D
Sprite2D 用来显示一张 2D 图片。
它一般不会单独作为复杂对象的根节点,而是作为子节点挂在角色、物品、敌人下面。
比如:
Player / CharacterBody2D
└── Sprite2D
常用场景:
显示玩家图片
显示敌人图片
显示道具图片
显示树、石头、宝箱
显示技能图标
如果你只是想让一张图片出现在场景里,可以直接用 Sprite2D。
但如果这个图片要移动、碰撞、交互,通常会用其他节点作为根节点,再把 Sprite2D 放进去。
比如宝箱:
Chest / Area2D
├── Sprite2D
└── CollisionShape2D
3. AnimatedSprite2D
AnimatedSprite2D 用来播放帧动画。
它适合使用一组图片帧组成的动画,比如:
角色走路
敌人攻击
火焰燃烧
水流动画
金币旋转
它需要配合 SpriteFrames 资源使用。
结构一般是:
Player / CharacterBody2D
├── AnimatedSprite2D
└── CollisionShape2D
如果你有一张角色动作精灵图,可以把它切成多帧,然后放进 AnimatedSprite2D。
适合简单动画。
如果动画里还要同时控制碰撞框、音效、武器判定、粒子效果,那更推荐用 AnimationPlayer。
4. AnimationPlayer
AnimationPlayer 是 Godot 里非常重要的动画节点。
它不只是播放图片动画,它可以控制几乎任何属性。
比如它可以控制:
Sprite2D 的 texture
Node2D 的 position
Sprite2D 的 modulate
CollisionShape2D 是否启用
AudioStreamPlayer 播放声音
角色攻击时武器判定框开启
UI 面板透明度变化
它适合做更复杂、更精确的动画。
比如攻击动画:
Player / CharacterBody2D
├── Sprite2D
├── HitBox / Area2D
├── CollisionShape2D
└── AnimationPlayer
攻击开始时:
播放挥剑动画
开启 HitBox 碰撞
播放攻击音效
几帧后关闭 HitBox
这类逻辑用 AnimationPlayer 就很方便。
5. AnimationTree
AnimationTree 是更高级的动画状态机。
它适合角色动画很多的情况。
比如:
idle
walk
run
attack
hurt
death
roll
cast
如果你只用 AnimationPlayer,动画切换逻辑可能会写得很乱。
AnimationTree 可以做:
动画状态机
混合动画
根据方向切换动画
根据速度平滑过渡
一般中后期再用。
初学阶段可以先用 AnimatedSprite2D 或 AnimationPlayer。
五、2D 物理节点
2D 物理节点是 Godot 做角色、碰撞、攻击范围、障碍物时最常用的一类。
1. CharacterBody2D
CharacterBody2D 最常用来做“由代码控制移动的角色”。
比如:
玩家
NPC
敌人
可移动怪物
横版游戏角色
俯视角 RPG 角色
官方文档说明,CharacterBody2D 用于通过代码实现控制的身体,它移动时会检测碰撞,但不会自动受到重力、摩擦等物理属性影响;也就是说,它需要你写代码控制移动,但你能获得更精确的控制。
典型结构:
Player / CharacterBody2D
├── Sprite2D 或 AnimatedSprite2D
├── CollisionShape2D
├── AnimationPlayer
└── Camera2D
俯视角 RPG 玩家一般就用它:
extends CharacterBody2D
@export var speed := 120.0
func _physics_process(delta):
var direction := Input.get_vector("move_left", "move_right", "move_up", "move_down")
velocity = direction * speed
move_and_slide()
适合你的《旧日秘境》这种 RPG 项目。
玩家角色应该优先用:
CharacterBody2D
而不是 RigidBody2D。
因为玩家移动通常需要“精准可控”,而不是让物理系统自己算。
2. StaticBody2D
StaticBody2D 用来做不会移动的物理物体。
比如:
墙
石头
房子
树干
桌子
河边障碍
地图边界
不可穿越的山体
典型结构:
Rock / StaticBody2D
├── Sprite2D
└── CollisionShape2D
玩家撞到 StaticBody2D 就会被挡住。
在 RPG 里,常见用法是:
树的底部有碰撞
房子的墙有碰撞
水边不能走
悬崖不能走
如果你用 TileMapLayer 做地图,也可以在 TileSet 里给某些 tile 设置碰撞,这样就不需要每块石头都手动放 StaticBody2D。
3. RigidBody2D
RigidBody2D 是受物理系统控制的刚体。
官方文档说明,它实现完整的 2D 物理,不能直接像普通角色那样控制位置,而是应该通过力、冲量、重力等方式影响它。
适合:
会被推开的箱子
会滚动的石头
掉落的物品
被爆炸炸飞的物体
物理弹球
碎片
不适合:
玩家主角
普通 NPC
需要精准路线的敌人
RPG 角色移动
比如一个可以推动的箱子:
Box / RigidBody2D
├── Sprite2D
└── CollisionShape2D
如果你发现自己想写:
rigid_body.position += Vector2(...)
那大概率你用错了,应该改用 CharacterBody2D 或 Node2D。
4. Area2D
Area2D 是“检测区域”,不是实体墙。
官方文档说明,Area2D 是一个由 CollisionShape2D 或 CollisionPolygon2D 定义的 2D 区域,它可以检测其他碰撞对象进入、离开,以及当前有哪些对象重叠在区域内。
它常用来做:
攻击范围
拾取范围
传送门
NPC 对话触发区
宝箱交互范围
陷阱区域
怪物警戒范围
进入房屋触发区
剧情触发点
比如宝箱:
Chest / Area2D
├── Sprite2D
└── CollisionShape2D
玩家进入宝箱范围后,显示:
按 E 打开宝箱
比如传送门:
DoorArea / Area2D
└── CollisionShape2D
玩家进入后切换场景。
比如怪物感知范围:
Enemy / CharacterBody2D
├── Sprite2D
├── CollisionShape2D
└── DetectArea / Area2D
└── CollisionShape2D
当玩家进入 DetectArea,怪物开始追击。
5. CollisionShape2D
CollisionShape2D 是碰撞形状。
它自己不能独立工作,必须挂在这些节点下面:
CharacterBody2D
StaticBody2D
RigidBody2D
Area2D
常见形状:
RectangleShape2D 矩形
CircleShape2D 圆形
CapsuleShape2D 胶囊
SegmentShape2D 线段
WorldBoundaryShape2D 世界边界
例如:
Player / CharacterBody2D
└── CollisionShape2D
如果没有 CollisionShape2D,你的角色虽然是 CharacterBody2D,但它没有实际碰撞体,就像一个没有边界的幽灵。
6. CollisionPolygon2D
CollisionPolygon2D 是多边形碰撞。
适合不规则形状:
山体
湖边
悬崖
大型岩石
不规则建筑
但不要滥用。
简单物体优先用 CollisionShape2D,性能更好,也更容易维护。
六、TileMap 和地图节点
1. TileMapLayer
在 Godot 4.3 之后,TileMap 逐渐被新的 TileMapLayer 工作流取代。TileMapLayer 用于 2D 网格地图,它使用 TileSet 里的图块来绘制地图;和旧的 TileMap 不同,TileMapLayer 只表示一层地图,如果要多层地图,可以使用多个 TileMapLayer。
这对 RPG 很重要。
一个地图通常不是一层,而是多层:
World / Node2D
├── GroundLayer / TileMapLayer
├── DecorationBelowLayer / TileMapLayer
├── ObjectLayer / TileMapLayer
├── AbovePlayerLayer / TileMapLayer
└── Player / CharacterBody2D
比如:
GroundLayer:草地、泥土、道路
WaterLayer:水面、河流
ObjectLayer:树、石头、房子
AbovePlayerLayer:树冠、屋顶、桥上层
对于你现在做的 RPG,建议地图结构这样分:
Map_Forest / Node2D
├── Ground / TileMapLayer
├── Water / TileMapLayer
├── Objects / TileMapLayer
├── AbovePlayer / TileMapLayer
├── YSortObjects / Node2D
├── Player / CharacterBody2D
└── Camera2D
2. TileSet
TileSet 不是节点,而是资源。
但它和地图强相关。
它负责定义:
每个 tile 对应图片哪一块
哪些 tile 有碰撞
哪些 tile 是地形连接
哪些 tile 有导航
哪些 tile 有自定义数据
比如你有一张 32x32 的瓦片图,导入后要创建 TileSet,然后告诉 Godot:
草地 tile
道路 tile
水 tile
墙 tile
树 tile
房子 tile
如果某些 tile 不能走,就给它们设置 collision。
比如:
水:有碰撞,玩家不能走进去
墙:有碰撞
树干:有碰撞
草地:没有碰撞
道路:没有碰撞
3. Marker2D
Marker2D 是一个位置标记节点。
它没有实际显示内容,主要用来标记坐标。
常用场景:
玩家出生点
怪物刷新点
NPC 站立点
传送门目标点
摄像机边界点
子弹发射点
技能生成点
比如:
Map_Forest / Node2D
├── SpawnPoints / Node2D
│ ├── PlayerSpawn / Marker2D
│ ├── SlimeSpawn01 / Marker2D
│ └── SlimeSpawn02 / Marker2D
然后代码里可以这样:
player.global_position = $SpawnPoints/PlayerSpawn.global_position
这个节点非常适合做“编辑器里可视化摆点”。
七、显示和绘制相关节点
1. CanvasItem
CanvasItem 是 2D 显示相关节点的基类。
你平时不会直接创建它,但很多节点都继承它:
Node2D
Control
Sprite2D
Label
TextureRect
它提供:
visible
modulate
self_modulate
z_index
show()
hide()
所以你会发现 Sprite2D 和 Control 都有 visible,这是因为它们上层都属于 CanvasItem 系列。
2. CanvasLayer
CanvasLayer 用来创建独立的 2D 绘制层。
最常见用途:UI。
比如:
Main / Node
├── World / Node2D
└── UI / CanvasLayer
├── HUD / Control
└── DialogBox / Control
为什么 UI 要放 CanvasLayer?
因为游戏世界会跟着摄像机移动,而 UI 不应该跟着地图移动。
比如玩家走路时:
地图会滚动
玩家位置会变化
血条 UI 应该固定在屏幕上
背包按钮应该固定在右上角
任务栏应该固定在左侧
这些就应该放在 CanvasLayer 下面。
3. Camera2D
Camera2D 是 2D 摄像机。
常用场景:
跟随玩家
限制地图边界
做镜头震动
切换关注目标
剧情镜头移动
典型结构:
Player / CharacterBody2D
└── Camera2D
或者:
World / Node2D
├── Player
└── Camera2D
如果相机是玩家子节点,它会天然跟随玩家。
如果相机独立放在 World 下面,就更适合做复杂镜头,比如剧情移动、平滑跟随、多目标切换。
RPG 初期建议直接把 Camera2D 放在玩家下面:
Player / CharacterBody2D
├── AnimatedSprite2D
├── CollisionShape2D
└── Camera2D
4. ParallaxBackground 和 ParallaxLayer
这两个节点用来做视差背景。
适合:
横版游戏
远景山脉
云层
背景森林
天空层
对于俯视角 RPG 不一定常用。
但如果你做标题界面、远景背景、过场场景,它们会很有用。
八、UI 节点
Godot 的 UI 节点基本都继承自 Control。
官方文档说明,Control 是所有 UI 节点的基类,它有矩形区域、锚点、相对父节点或视口的位置偏移,并且会随着父节点或屏幕尺寸变化自动更新。
你可以把 Control 理解成前端里的 div。
1. Control
Control 是 UI 根节点常用选择。
比如:
HUD / Control
├── HealthBar
├── ManaBar
└── CoinLabel
它本身不一定显示内容,但可以作为 UI 容器。
适合:
HUD 根节点
背包面板根节点
设置面板根节点
对话框根节点
菜单界面根节点
2. Label
Label 用来显示文字。
常用:
角色名字
任务文本
金币数量
提示文字
伤害数字
比如:
CoinLabel / Label
3. RichTextLabel
RichTextLabel 是更强的文字显示节点。
适合:
带颜色的文字
带图标的文字
剧情对话
任务描述
物品说明
滚动文本
比如对话系统:
DialogBox / Control
├── SpeakerName / Label
└── DialogText / RichTextLabel
如果你要做 RPG 对话框,推荐用 RichTextLabel。
4. Button
Button 是按钮。
常用:
开始游戏
继续游戏
打开背包
确认
取消
设置
退出
结构:
MainMenu / Control
├── StartButton / Button
├── LoadButton / Button
└── QuitButton / Button
按钮通常连接 pressed 信号:
func _on_start_button_pressed():
get_tree().change_scene_to_file("res://scenes/world/map_forest.tscn")
5. TextureButton
TextureButton 是图片按钮。
适合:
背包图标按钮
技能栏按钮
装备栏按钮
地图按钮
手机游戏虚拟按钮
如果你的按钮是美术图标,而不是普通矩形按钮,用它更合适。
6. TextureRect
TextureRect 用来在 UI 里显示图片。
注意它是 UI 节点,不是世界里的 Sprite。
区别:
Sprite2D:放在游戏世界里,会受摄像机影响
TextureRect:放在 UI 里,固定在屏幕界面上
常用:
头像
物品图标
技能图标
背景面板
菜单图片
比如:
InventorySlot / Control
├── Icon / TextureRect
└── CountLabel / Label
7. ProgressBar
ProgressBar 用来显示进度条。
常用:
血条
蓝条
经验条
加载进度
蓄力条
比如:
HUD / Control
├── HealthBar / ProgressBar
└── ExpBar / ProgressBar
8. TextureProgressBar
TextureProgressBar 是带图片样式的进度条。
适合正式游戏 UI。
比如:
有美术边框的血条
圆形技能冷却
特殊魔法能量条
前期可以先用 ProgressBar,后期换成 TextureProgressBar。
9. Panel
Panel 是 UI 面板。
适合:
背包背景
设置窗口
弹窗
任务面板
对话框背景
比如:
InventoryPanel / Panel
├── Title / Label
├── GridContainer
└── CloseButton
10. PanelContainer
PanelContainer 是带容器能力的面板。
它通常用于自动布局。
如果你想让一个面板包住里面的内容,用 PanelContainer 很方便。
11. MarginContainer
MarginContainer 用来给子节点加边距。
类似 CSS 里的 padding。
比如:
DialogBox / PanelContainer
└── MarginContainer
└── DialogText / RichTextLabel
12. VBoxContainer 和 HBoxContainer
这两个是 UI 自动布局节点。
VBoxContainer 是纵向排列。
VBoxContainer
├── Button
├── Button
└── Button
类似:
display: flex;
flex-direction: column;
HBoxContainer 是横向排列。
HBoxContainer
├── Icon
├── Label
└── Button
类似:
display: flex;
flex-direction: row;
13. GridContainer
GridContainer 是网格布局。
适合:
背包格子
技能栏
商店商品列表
装备栏
物品仓库
比如背包:
InventoryPanel / Panel
└── GridContainer
├── Slot01
├── Slot02
├── Slot03
└── Slot04
14. ScrollContainer
ScrollContainer 用于可滚动区域。
适合:
任务列表
背包列表
设置项很多的页面
图鉴
日志
15. LineEdit
单行输入框。
适合:
输入角色名
输入存档名
搜索物品
聊天输入
16. TextEdit
多行输入框。
游戏里不算常用,但做编辑器工具、开发调试面板时有用。
17. OptionButton
下拉选择框。
适合:
分辨率选择
语言选择
画质选择
难度选择
18. CheckBox
勾选框。
适合:
全屏开关
音乐开关
显示伤害数字
开启自动保存
19. Slider / HSlider / VSlider
滑动条。
常用:
音乐音量
音效音量
亮度
鼠标灵敏度
九、音频节点
1. AudioStreamPlayer
普通音频播放器。
适合播放不依赖空间位置的声音:
背景音乐
UI 点击音
菜单音效
系统提示音
比如:
AudioManager / Node
├── BGMPlayer / AudioStreamPlayer
└── UIPlayer / AudioStreamPlayer
2. AudioStreamPlayer2D
2D 空间音频。
它的位置会影响声音听起来的方向和距离。
适合:
怪物叫声
河流声
火堆声
脚步声
武器碰撞声
远处爆炸声
比如:
Campfire / Node2D
├── Sprite2D
└── AudioStreamPlayer2D
玩家靠近火堆,声音更明显;离远了,声音变小。
3. AudioStreamPlayer3D
3D 游戏使用,2D RPG 基本用不到。
十、计时和异步相关节点
1. Timer
Timer 是定时器节点。
常用场景:
怪物每隔几秒攻击一次
技能冷却
剧情延迟
自动保存
天气切换
日夜循环
生成怪物
比如:
Enemy / CharacterBody2D
└── AttackTimer / Timer
代码:
func _on_attack_timer_timeout():
attack()
Timer 很适合做“过一段时间执行”的逻辑。
2. Tween
Godot 4 里更多时候会用代码创建 tween,而不是手动添加 Tween 节点。
Tween 适合做平滑过渡:
UI 淡入淡出
角色受击闪烁
相机平滑移动
物品飞到背包
血条缓慢变化
比如:
var tween := create_tween()
tween.tween_property($Panel, "modulate:a", 0.0, 0.3)
十一、导航寻路节点
1. NavigationRegion2D
NavigationRegion2D 用来定义可寻路区域。
适合:
敌人自动追玩家
NPC 自动走到指定地点
村民巡逻
怪物绕过障碍物
比如:
World / Node2D
├── NavigationRegion2D
├── Player
└── Enemy
2. NavigationAgent2D
NavigationAgent2D 通常挂在需要寻路的角色身上。
比如:
Enemy / CharacterBody2D
├── Sprite2D
├── CollisionShape2D
└── NavigationAgent2D
它负责帮敌人计算路径。
大概逻辑是:
玩家在哪
敌人设置目标点为玩家位置
NavigationAgent2D 计算下一步方向
敌人移动过去
3. NavigationObstacle2D
用于动态障碍物。
比如:
可移动箱子
临时堵路物
移动 NPC
初期可以不用急着学。
十二、光照和视觉效果节点
1. PointLight2D
2D 点光源。
适合:
火把
灯笼
魔法光球
营火
窗户透出的光
比如:
Torch / Node2D
├── Sprite2D
└── PointLight2D
你的 RPG 如果想做夜晚、洞穴、雾气、神秘森林,PointLight2D 会很有用。
2. DirectionalLight2D
2D 方向光。
适合模拟:
太阳光
月光
整体环境方向光
3. CanvasModulate
CanvasModulate 用来整体改变 2D 世界颜色。
常用来做:
白天
黄昏
夜晚
中毒滤镜
进入梦境
进入黑暗区域
比如夜晚:
World / Node2D
├── CanvasModulate
├── TileMapLayer
└── Player
把 CanvasModulate 调暗后,整个世界都会变暗。
再配合 PointLight2D,就能做火把照亮黑夜的效果。
4. GPUParticles2D
粒子效果节点。
适合:
雨
雪
雾
火花
魔法粒子
落叶
灰尘
攻击特效
比如:
Weather / Node2D
├── RainParticles / GPUParticles2D
├── SnowParticles / GPUParticles2D
└── FogParticles / GPUParticles2D
对于你的游戏,之后做天气系统时会经常用到。
5. CPUParticles2D
CPU 粒子。
相比 GPUParticles2D,它更兼容一些老设备,但性能通常不如 GPU 粒子。
一般优先用 GPUParticles2D。
十三、资源加载和实例化常用节点思路
这里要特别讲一下:很多时候你不是“创建一个节点”,而是“创建一个场景,然后实例化”。
比如你有:
Slime.tscn
Potion.tscn
DamageNumber.tscn
Fireball.tscn
在代码里:
var slime_scene: PackedScene = preload("res://scenes/enemies/slime.tscn")
var slime = slime_scene.instantiate()
add_child(slime)
这里的 PackedScene 不是节点,而是一个“打包好的场景资源”。
它就像前端里:
组件定义:Slime.vue
组件实例:页面里真正渲染出来的 Slime
Godot 里:
PackedScene:场景模板
instantiate():创建实例
add_child():挂到场景树里
十四、3D 常用节点
虽然你现在主要做 2D RPG,但知道一下 3D 节点也有帮助。
1. Node3D
3D 世界里的基础节点。
类似 2D 的 Node2D。
它有:
position
rotation
scale
transform
2. MeshInstance3D
显示 3D 模型。
适合:
角色模型
场景模型
道具模型
建筑模型
3. CharacterBody3D
3D 角色控制。
适合:
第一人称角色
第三人称角色
3D 怪物
3D NPC
4. StaticBody3D
3D 静态碰撞体。
比如:
墙
地面
建筑
山体
不可移动障碍
5. RigidBody3D
3D 物理刚体。
比如:
箱子
球
物理道具
可被撞飞的物体
6. Area3D
3D 检测区域。
比如:
触发剧情
进入区域
拾取物品
攻击范围
7. Camera3D
3D 摄像机。
8. DirectionalLight3D / OmniLight3D / SpotLight3D
3D 光源。
对应:
DirectionalLight3D:太阳光
OmniLight3D:点光源
SpotLight3D:聚光灯
十五、常见游戏对象应该用什么节点
玩家角色
推荐:
Player / CharacterBody2D
├── AnimatedSprite2D
├── CollisionShape2D
├── AnimationPlayer
├── Camera2D
└── InteractArea / Area2D
作用:
CharacterBody2D:控制移动和碰撞
AnimatedSprite2D:显示角色动画
CollisionShape2D:角色身体碰撞
AnimationPlayer:控制复杂动画
Camera2D:跟随玩家
Area2D:检测可交互物体
敌人
推荐:
Enemy / CharacterBody2D
├── AnimatedSprite2D
├── CollisionShape2D
├── DetectionArea / Area2D
├── AttackArea / Area2D
├── NavigationAgent2D
└── AnimationPlayer
作用:
CharacterBody2D:敌人移动
DetectionArea:发现玩家
AttackArea:攻击范围
NavigationAgent2D:寻路
AnimationPlayer:攻击、受击、死亡动画
NPC
推荐:
NPC / CharacterBody2D 或 Area2D
├── AnimatedSprite2D
├── CollisionShape2D
├── TalkArea / Area2D
└── DialogueMarker / Marker2D
如果 NPC 会走动,用 CharacterBody2D。
如果 NPC 只是站着不动,也可以用 StaticBody2D 或 Area2D。
宝箱
推荐:
Chest / Area2D
├── Sprite2D
├── CollisionShape2D
└── AnimationPlayer
作用:
Area2D:检测玩家是否靠近
Sprite2D:显示宝箱
CollisionShape2D:交互范围
AnimationPlayer:开箱动画
如果宝箱本身要挡住玩家,可以再加一个 StaticBody2D,或者让宝箱根节点改成 StaticBody2D,旁边挂一个 Area2D 做交互范围:
Chest / StaticBody2D
├── Sprite2D
├── CollisionShape2D
├── InteractArea / Area2D
│ └── CollisionShape2D
└── AnimationPlayer
掉落物
推荐:
DropItem / Area2D
├── Sprite2D
└── CollisionShape2D
玩家碰到后拾取。
门和传送点
推荐:
Door / Area2D
├── Sprite2D
└── CollisionShape2D
玩家进入区域后切换地图。
墙、石头、树干
推荐:
StaticBody2D
├── Sprite2D
└── CollisionShape2D
或者直接在 TileSet 里设置 tile 碰撞。
攻击判定
推荐:
AttackHitBox / Area2D
└── CollisionShape2D
通常攻击判定不是用 CharacterBody2D,而是用 Area2D。
比如玩家挥剑时,短暂开启 AttackHitBox。
技能子弹
推荐:
Fireball / Area2D
├── Sprite2D
├── CollisionShape2D
├── GPUParticles2D
└── Timer
作用:
Area2D:碰到敌人触发伤害
Sprite2D:显示火球
Particles:拖尾特效
Timer:几秒后自动消失
如果技能需要真实物理反弹,可以用 RigidBody2D,但普通 RPG 技能大多用 Area2D 更好控制。
UI 主界面
推荐:
UI / CanvasLayer
└── HUD / Control
├── HealthBar / ProgressBar
├── ManaBar / ProgressBar
├── CoinLabel / Label
└── SkillBar / HBoxContainer
对话框
推荐:
DialogUI / CanvasLayer
└── DialogBox / Panel
├── SpeakerName / Label
├── DialogText / RichTextLabel
└── NextIcon / TextureRect
背包
推荐:
InventoryUI / CanvasLayer
└── InventoryPanel / Panel
├── Title / Label
├── GridContainer
│ ├── Slot01 / TextureButton
│ ├── Slot02 / TextureButton
│ └── Slot03 / TextureButton
└── CloseButton / Button
十六、根节点应该怎么选
这是初学者最容易纠结的地方。
你可以按这个规则选:
不显示、不需要位置,只做逻辑
用:
Node
比如:
GameManager
SaveManager
QuestManager
2D 世界里的普通对象
用:
Node2D
比如:
装饰容器
地图根节点
特效容器
2D 可控制角色
用:
CharacterBody2D
比如:
玩家
敌人
会移动的 NPC
2D 不动的障碍物
用:
StaticBody2D
比如:
墙
石头
树干
房子
2D 受物理影响的物体
用:
RigidBody2D
比如:
被推的箱子
掉落的石块
滚动的木桶
只检测进入、离开、重叠
用:
Area2D
比如:
攻击范围
拾取范围
传送点
对话范围
陷阱区域
UI 根节点
用:
Control
如果要固定在屏幕上,外面再套:
CanvasLayer
十七、Godot 节点选择速查表
需求:玩家移动
推荐:CharacterBody2D
需求:敌人移动
推荐:CharacterBody2D
需求:地图瓦片
推荐:TileMapLayer
需求:显示一张图片
推荐:Sprite2D
需求:播放帧动画
推荐:AnimatedSprite2D
需求:复杂动画控制
推荐:AnimationPlayer
需求:攻击范围
推荐:Area2D
需求:拾取道具
推荐:Area2D
需求:传送门
推荐:Area2D
需求:不会动的墙
推荐:StaticBody2D
需求:会被物理推动的箱子
推荐:RigidBody2D
需求:角色碰撞框
推荐:CollisionShape2D
需求:不规则碰撞
推荐:CollisionPolygon2D
需求:摄像机跟随
推荐:Camera2D
需求:固定 UI
推荐:CanvasLayer + Control
需求:血条
推荐:ProgressBar 或 TextureProgressBar
需求:背包格子
推荐:GridContainer + TextureButton
需求:文字
推荐:Label 或 RichTextLabel
需求:音效
推荐:AudioStreamPlayer 或 AudioStreamPlayer2D
需求:定时执行
推荐:Timer
需求:生成点
推荐:Marker2D
需求:粒子特效
推荐:GPUParticles2D
需求:火把光源
推荐:PointLight2D
需求:整体变暗、夜晚
推荐:CanvasModulate
需求:敌人寻路
推荐:NavigationAgent2D + NavigationRegion2D
十八、以你的 RPG 项目为例,推荐基础场景结构
你的《旧日秘境》这种 2D RPG,基础地图可以这样设计:
Main / Node
├── World / Node2D
│ ├── Map_Forest / Node2D
│ │ ├── Ground / TileMapLayer
│ │ ├── Water / TileMapLayer
│ │ ├── Objects / TileMapLayer
│ │ ├── AbovePlayer / TileMapLayer
│ │ ├── SpawnPoints / Node2D
│ │ │ └── PlayerSpawn / Marker2D
│ │ └── Interactables / Node2D
│ │ ├── Chest
│ │ └── Door
│ ├── Player / CharacterBody2D
│ │ ├── AnimatedSprite2D
│ │ ├── CollisionShape2D
│ │ ├── InteractArea / Area2D
│ │ │ └── CollisionShape2D
│ │ ├── Camera2D
│ │ └── AnimationPlayer
│ ├── Enemies / Node2D
│ └── Items / Node2D
├── UI / CanvasLayer
│ ├── HUD / Control
│ ├── DialogUI / Control
│ └── InventoryUI / Control
├── GameManager / Node
├── AudioManager / Node
└── SceneManager / Node
这个结构比较适合长期扩展。
以后你要加:
天气系统
昼夜系统
四季系统
战斗系统
任务系统
背包系统
对话系统
怪物系统
地图切换
都可以继续往里面挂,不会一开始就乱成一坨毛线团。
十九、初学者最容易犯的节点选择错误
错误一:玩家用 RigidBody2D
很多人看到“物理身体”就想用 RigidBody2D 做玩家。
但 RPG 玩家应该用:
CharacterBody2D
因为玩家需要精确控制。
RigidBody2D 更适合被物理影响的物体。
错误二:UI 用 Sprite2D
如果是游戏世界里的图片,用 Sprite2D。
如果是界面上的图片,用 TextureRect。
区别:
Sprite2D:在地图里
TextureRect:在 UI 里
错误三:碰撞节点单独放
CollisionShape2D 不能自己工作。
它必须放在:
CharacterBody2D
StaticBody2D
RigidBody2D
Area2D
下面。
错误结构:
Player / Node2D
└── CollisionShape2D
这个碰撞不会按你想的方式工作。
正确结构:
Player / CharacterBody2D
└── CollisionShape2D
错误四:所有东西都放在一个场景里
不要把所有玩家、敌人、地图、UI、背包、对话都堆在一个巨大场景里。
应该拆成:
Player.tscn
Enemy.tscn
Chest.tscn
DialogUI.tscn
InventoryUI.tscn
Map_Forest.tscn
Main.tscn
这样才能维护。
错误五:所有逻辑都写在 Player.gd
玩家移动可以在 Player。
但这些不应该都写在 Player:
背包系统
任务系统
存档系统
天气系统
地图切换系统
音频系统
这些应该拆成独立管理节点或 Autoload。
二十、节点学习顺序建议
你不用一开始把所有节点都学完。
建议按这个顺序:
第一阶段:会搭 2D 场景
先学:
Node
Node2D
Sprite2D
AnimatedSprite2D
CharacterBody2D
CollisionShape2D
Camera2D
TileMapLayer
目标:
能做一个地图
角色能显示
角色能移动
角色不能穿墙
摄像机能跟随
第二阶段:会交互
再学:
Area2D
Timer
Marker2D
AnimationPlayer
AudioStreamPlayer2D
目标:
能开宝箱
能和 NPC 对话
能传送地图
能播放动画
能播放音效
第三阶段:会做 UI
再学:
CanvasLayer
Control
Label
RichTextLabel
Button
TextureRect
ProgressBar
Panel
GridContainer
HBoxContainer
VBoxContainer
目标:
血条
金币
对话框
背包
菜单
设置界面
第四阶段:会做游戏系统
再学:
NavigationAgent2D
NavigationRegion2D
GPUParticles2D
PointLight2D
CanvasModulate
Resource
PackedScene
Autoload
目标:
敌人寻路
天气
昼夜
技能
怪物刷新
任务系统
背包数据
存档
二十一、总结
Godot 的节点并不是孤立使用的,而是通过“组合”来形成一个游戏对象。
你不应该问:
我要用哪个节点做玩家?
而应该问:
玩家这个对象需要哪些能力?
然后拆开:
需要移动和碰撞:CharacterBody2D
需要显示图片:AnimatedSprite2D
需要碰撞形状:CollisionShape2D
需要相机跟随:Camera2D
需要动画控制:AnimationPlayer
需要交互范围:Area2D
所以最终玩家不是一个节点,而是一组节点:
Player / CharacterBody2D
├── AnimatedSprite2D
├── CollisionShape2D
├── Camera2D
├── AnimationPlayer
└── InteractArea / Area2D
这就是 Godot 的核心思想:
一个节点负责一种能力
多个节点组合成一个对象
多个对象组合成一个场景
多个场景组合成一个游戏
你只要理解了这个,Godot 就不会再像一堆陌生按钮,而会更像你熟悉的前端组件树。只是这次组件不是渲染网页,而是在组织一个真正能动、能碰撞、能交互的游戏世界。
如果您觉得这篇文章有帮助,请点个赞吧~
评论
请登录后发表评论
去登录