游戏事件系统
在 Unity 中把事件保存为资产,用编辑器配置回调和流程,也可以通过类型化 C# API 接入游戏逻辑
需要从场景或代码触发事件,并查看哪些动作会响应的开发者
上图把事件编辑器、Inspector、FlowGraph 和监控器放在一起,它们围绕同一批事件资产工作,从数据库选中事件后,可以配置回调和后续流程,再在 Play Mode 观察它们何时执行
从事件资产接入场景
把事件保存在 ScriptableObject 数据库中,发送脚本和接收组件引用同一资产,脚本调用 Raise() 时,已绑定的回调就能接到信号

上图中央的 Game Event Manager 连接数据库和 FlowGraph,左侧工具负责创建与配置事件,右侧的组件和 C# 脚本负责运行时接入,底部的 Monitor 用于检查实际执行
- 在 Game Event Editor 选择数据库,在 Game Event Creator 选择无参数、单参数或 Sender + Args 类型并创建事件
- 在 Game Event Behavior 为管理器绑定 UnityEvent 回调,或在单个组件的 Inspector 配置 Receiver 动作条件
- 使用 Game Event Raiser 或 C# 调用
Raise(),再打开 Game Event Monitor 查看回调、耗时和流程节点
以下脚本通过事件字段保存资产引用,Unity Inspector 会按字段类型筛选事件
// 事件是资产,而非魔法字符串
[GameEventDropdown] public GameEvent onPlayerDeath;
[GameEventDropdown] public Int32GameEvent onScoreChanged;
void Die() {
onPlayerDeath.Raise(); // 类型安全,资产引用
}
通过 Unity 重命名或移动数据库资产时,引用使用的文件 GUID 随 .meta 保留,数据库中的事件还有独立的内部 GUID,可用于运行时查询
# PlayerDeath.asset.meta
guid: a7f3c21e9b4d8f6e2d1a9c8b7e6f5a4d
上面的 .meta 片段表示 Unity 文件 GUID,数据库内的事件用其内部 GUID 区分
配置事件之间的执行关系
当一个事件要启动多个后续动作时,在 FlowGraph 连接 Trigger 节点,分别配置条件和优先级

上图中同一个源事件连到多个目标,流程到达源节点后按优先级启动符合条件的分支
需要按固定次序执行步骤时,将后续事件接为 Chain 节点

上图中的节点沿一条链向后推进,每一步可以配置延迟或条件,以便先完成当前操作再进入下一步
在同一图中组合 Trigger 和 Chain,可让各分支按各自的时序运行

上图从一个源事件分出多条路径,其中一条路径再顺序执行后续步骤,运行时可通过 Automation 检查事件链的实际进度
在 Inspector 中绑定参数
为自定义参数创建事件时,CodeGen 为 GameEvent<T> 生成具体的事件类,Inspector 可在该类型的字段上提供事件选择和原生 UnityEvent 回调
// ❌ Unity无法序列化这个
[SerializeField] private GameEvent<PlayerData> onPlayerDataChanged;
用 Creator 创建 PlayerData 事件后,脚本可以直接声明生成的类型
// ✅ 自动生成的具体类
[GameEventDropdown] public PlayerDataGameEvent onPlayerDataChanged;
// 生成的代码(自动):
[Serializable]
public class PlayerDataGameEvent : GameEvent<PlayerData> { }
生成的 Event Action 使用类型化派发,IL2CPP 构建前运行 Bake AOT Conditions,让 Player 能按 ID 查到条件求值器
在运行时加载与检查
动态加载内容时,通过 数据库与查询 API 注册数据库,再按内部 GUID、名称、分类或类型查找事件,已安装 Addressables 的项目也可以按地址或数据库 GUID 加载并持有租约
监听策略提供普通、优先级、条件和持久化监听,触发与调度负责延迟、重复和取消,编程式流程可以在运行时建立 Trigger 或 Chain 关系
需要排查执行开销时,使用 Game Event Monitor 在实际项目的 Play Mode 查看调用次数、监听器和执行时间,测得的耗时取决于运行环境与绑定的动作
"我开发这个系统是因为厌倦了在自己的项目中与'隐形意大利面代码'作斗争
作为独立开发者,我需要一个能够平衡可视化清晰度与原始编码能力的工具——而且不能有性能损失
TinyGiants 是我对专业级工具的承诺,这些工具我每天都在自己的游戏中使用" — [TinyGiants] 来自中国
导航路线图
首次使用时打开快速开始,需要配置回调或流程时,按下表进入对应窗口的操作指南
1. 介绍
事件即资产架构的基础设置和核心理念
| 页面 | 描述 |
|---|---|
| 项目结构 | 理解目录布局、文件夹保护和模块化组织 |
| 安装 | 初始化插件并设置自动静态重置管线 |
2. 可视化工作流
将不可见代码转化为有形可视化仪表板的管理工具
| 页面 | 描述 |
|---|---|
| 系统仪表板 | 基于资产的工作流和GUID身份系统概览 |
| 数据库与流程图 | 处理多数据库和多流程图设置以及数据库健康维护 |
| 编辑游戏事件 | 使用仪表板进行批量编辑、搜索和分类 |
| 创建游戏事件 | 使用模糊搜索批量向导快速生成事件资产 |
| 配置游戏事件 | 掌握带有可视状态标记和类型安全的Inspector绑定 |
| 触发游戏事件 | 学习如何调用事件并使用内置GameEventDropdown属性增强Inspector |
| 查找游戏事件 | 扫描场景以定位组件级事件依赖关系 |
| 可视化条件树 | 学习如何通过条件树配置控制事件动作的逻辑执行 |
3. 流程编排
使用节点可视化和构建复杂的多步骤逻辑序列
| 页面 | 描述 |
|---|---|
| 节点编辑器 | 管理GraphView画布、分组和基于快照的撤销/重做 |
| 节点连接器 | 混合执行模式的规则和实时连接验证 |
| 节点行为 | 配置节点级延迟、循环和参数转换逻辑 |
| 高级逻辑模式 | 构建无代码嵌套逻辑组和条件执行门控 |
4. 脚本与API
开发者的高性能C#集成和生命周期管理指南
| 页面 | 描述 |
|---|---|
| 触发与调度 | 编程式触发、延迟执行和任务句柄管理 |
| 监听策略 | 实现优先级、持久化和源感知(Sender)监听器 |
| 编程式流程 | 使用类型化谓词过滤运行时逻辑 |
| 数据库与查询 | 运行时数据库生命周期 + 按 GUID / 名称 / 分类 / 类型查找事件 |
| 最佳实践 | 清晰解耦和防止数据污染的架构技巧 |
| API参考 | 所有核心类和属性的详细技术文档 |
5. 工具与支持
专业生产环境的自动化和监控实用工具
| 页面 | 描述 |
|---|---|
| 代码生成与清理 | 使用三模式生成器和编译管线自动化 |
| 运行时监控器 | 实时性能分析、深度日志记录和警告系统 |
| AOT 条件烘焙 | 更新构建所用的条件注册表 |
| Addressables | 按需加载事件数据库并管理租约 |
| 社区与支持 | 访问更新、报告错误和获取技术支持 |
6. 示例
GES 2.3.0 随包提供 29 个 Unity 场景,分布在下列 15 个演示主题中
| ID | 示例页面 | 核心学习点 |
|---|---|---|
| 00 | 快速开始 | 创建、触发和绑定事件的最小工作流 |
| 01 | 空事件 | 使用无参数信号进行全局触发,如"关卡开始" |
| 02 | 基础类型事件 | 通过事件传递原始数据(int、float、string) |
| 03 | 自定义类型事件 | 利用CodeGen实现序列化自定义数据类和结构体 |
| 04 | 自定义Sender事件 | 使用源感知事件识别哪个实体触发了信号 |
| 05 | 优先级事件 | 精确控制多个监听器的执行顺序 |
| 06 | 条件事件 | 使用谓词仅在满足条件时执行回调 |
| 07 | 延迟事件 | 管理定时逻辑并使用任务句柄进行取消 |
| 08 | 重复事件 | 创建循环脉冲信号和自动化逻辑循环 |
| 09 | 持久化事件 | 处理场景转换期间的事件(DontDestroyOnLoad) |
| 10 | 触发器事件 | 将Unity的物理系统与游戏事件资产桥接 |
| 11 | 链式事件 | 使用流程编排图构建可视化顺序逻辑 |
| 12 | 多数据库 | 将事件隔离到不同资产中以实现模块化项目组织 |
| 13 | 运行时API | 通过C#脚本动态注册和注销监听器 |
| 14 | 运行时监控器 | 使用分析工具调试执行时间和GC分配 |
对于实践入门,我们建议首先遵循 示例00(快速开始),然后探索 可视化工作流 部分,了解编辑器工具如何简化您的开发