前言
在 Godot 中,信号系统(Signals) 是实现节点间通信的核心机制,它本质上是 Godot 引擎内置的、高度优化的“事件”系统。
与 C# 原生的 delegate/event 不同,Godot 信号跨语言(GDScript/C#/VisualScript)、支持编辑器可视化连接,并能自动处理生命周期(如节点释放时自动断开连接)。
因此在 Godot 项目中应优先使用信号而非手动实现 C# event。
Godot 信号的三种使用方式
- 连接引擎内置信号(如
Area2D.area_entered) - 自定义信号并发射
- 通过编辑器连接信号
示例场景:玩家进入区域 → 触发宝箱开启
我们将创建:
- 一个
Player(CharacterBody2D) - 一个
TreasureChest(Area2D+ 自定义信号)
下面以 C# 脚本 为例,完整演示如何在 Godot 4.x 中使用信号系统。
为宝箱定义自定义信号
为宝箱定义自定义信号(C#)
信号的定义必须以EventHandler结束,会自动生成前面名称的信号,比如下面示例的SignalName.ChestOpened
1 | using Godot; |
关键点:
- 使用
[Signal]特性声明信号。- 信号名会自动生成
SignalName.ChestOpened(字符串安全)。- 用
EmitSignal()发射信号。
玩家脚本
1 | // Player.cs |
连接信号两种方式
在 C# 中动态连接
推荐用于运行时逻辑
1 | // GameManager.cs 或 TreasureChest 的父节点 |
✅ 优点:灵活,适合动态生成的对象。
在 Godot 编辑器中连接
适合静态场景
- 选中
TreasureChest节点; - 在右侧 “Node” 面板 → “Signals” 标签;
- 找到
ChestOpened信号,双击; - 选择目标节点(如
UIController); - 输入方法名(如
OnChestOpened),点击“连接”。
Godot 会自动生成对应方法(如果不存在)。
断开信号(避免内存泄漏)
当节点被释放时,Godot 会自动断开其所有信号连接,所以通常无需手动断开。
但如果你在代码中跨场景或长期持有引用,建议显式断开:
1 | // 在节点销毁前(如 _ExitTree) |
重要提示
| 事项 | 说明 |
|---|---|
| 信号 vs C# event | 优先用 Godot 信号!它与引擎深度集成,支持编辑器、序列化、跨语言。 |
| 参数传递 | 信号可带参数(最多 9 个),在 [Signal] 委托中定义即可。 |
| 性能 | 信号调用比直接方法调用稍慢,但对游戏逻辑完全够用。 |
| 类型安全 | C# 中使用 SignalName.XXX 和 Callable.From() 可获得编译时检查。 |
带参数的信号示例
1 | [] |
绑定
1 | private TouchArea touchArea; |
总结
Godot 信号使用流程:
- 用
[Signal]声明信号; - 用
EmitSignal()发射; - 用
Connect()或编辑器连接; - 在目标方法中响应。
这是 Godot 官方推荐的节点通信方式,简洁、安全、高效。