跳到主要内容

游戏事件系统

一个生产就绪的可视化事件架构系统,专为Unity打造,将混乱的事件管理转变为可维护、可测试的工作流程。

Hero Diagram

来自作者

"我开发这个系统是因为厌倦了在自己的项目中与'隐形意大利面代码'作斗争。作为独立开发者,我需要一个能够平衡可视化清晰度与原始编码能力的工具——而且不能有性能损失。TinyGiants 是我对专业级工具的承诺,这些工具我每天都在自己的游戏中使用。" — [TinyGiants] 来自中国


系统存在的意义

问题所在

在传统的Unity开发中,事件会变成隐形的意大利面条代码:

  • 隐藏的依赖关系: 谁在监听?在哪里触发?祝你好运才能找到答案。
  • 运行时崩溃: 重命名一个方法,破坏10个场景对象。
  • 跨场景噩梦: 场景卸载时事件消失——到处都是内存泄漏和空引用。
  • 缺乏可见性: 复杂的事件链只存在于你的脑海中(以及过时的注释里)。
解决方案

TinyGiants.GameEventSystem 提供了一个 可视化优先、类型安全 的事件架构:

事件即资产 - 基于ScriptableObject,受GUID保护,经得起重构

可视化流程图 - 在一个窗口中查看你的事件链、触发器和条件

零反射运行时 - 表达式树编译,实现接近C++的性能

设计师友好 - 拖放式绑定,简单工作流无需编码

生产级工具 - 实时监控、引用查找、代码生成自动化


核心架构:运作原理

GameEventSystem 基于“管理-资产-动作”架构构建,旨在集中管理事件逻辑,同时保持执行的去中心化。

核心架构图

🏗️ 基础:GameEventManager 与数据库

系统的核心是 GameEventManager,它负责管理和维护事件数据库

  • 事件即资产:每个事件都是存储在数据库资产中的 ScriptableObject
  • 集中化管理GameEventEditorWindow 是系统的主控制中心。通过此窗口,您可以访问各类专项工具:
    • Creator (创建器):快速生成新的事件资产。
    • Behavior (行为) 与 Finder (查找器):配置事件属性并在场景中定位依赖关系。
    • FlowGraph (流图):以可视化方式设计复杂的多步骤事件序列。
    • Monitor (监控器):实时调试和性能跟踪。

🔄 混合工作流:可视化与代码

该系统无缝桥接了技术实现与创意设计之间的鸿沟:

  1. 直接代码集成:程序员只需在脚本中使用简单的 .Raise() 调用即可随时触发事件。
  2. 可视化 Inspector 绑定:设计师可以使用直观的下拉菜单在 Inspector 中直接绑定逻辑,完全消除了对“魔法字符串”或手动组件查找的需求。
  3. 实时监控Monitor 窗口提供事件活动的实时视图,帮助您在运行模式下验证数据流和执行时序。

💻 完整的 API 支持

虽然系统为设计师提供了强大的可视化界面,但它本质上是 API 优先的。 可视化编辑器中的所有功能均可通过 Runtime API 访问。 无论您喜欢在图表中构建事件链,还是通过 C# 代码动态注册/注销监听器,系统都能提供同等的性能与功能支持。


💡 为什么采用这种架构?

  • 解耦:发送者和接收者无需彼此了解;它们只需要引用同一个事件资产。
  • 可视化:标准事件中隐形的“面条代码”被可搜索的可视化数据库所取代。
  • 可靠性:由于事件是资产,当您重命名方法或移动文件时,引用不会丢失。

架构亮点

🏗️ 基础: ScriptableObject驱动

与基于字符串或单例的事件系统不同,事件是一等公民资产:

// 事件是资产,而非魔法字符串
[GameEventDropdown] public GameEvent onPlayerDeath;
[GameEventDropdown] public Int32GameEvent onScoreChanged;

void Die() {
onPlayerDeath.Raise(); // 类型安全,资产引用
}

优势:

  • 完全解耦 - 发送者永远不知道接收者。触发一次,通知所有。
  • 跨场景持久化 - 事件在场景加载/卸载中存活。
  • GUID标识 - 重命名文件、重组文件夹——引用永不断裂。
  • 多数据库支持 - 为大型团队提供模块化组织。
📖 GUID保护机制的工作原理

每个事件都有一个存储在 .meta 文件中的唯一GUID:

# PlayerDeath.asset.meta
guid: a7f3c21e9b4d8f6e2d1a9c8b7e6f5a4d

即使你将 PlayerDeath 重命名为 OnCharacterDied,Unity也会通过GUID维护引用。场景链接永不断裂。


🕸️ 可视化流程编排

不再需要在代码中寻找事件关系。流程编辑器 将不可见的逻辑转化为可维护的图表:

使用场景

🎯 触发器(扇出)

alt text

⛓️ 链式(顺序)

alt text

🔀 混合流程

混合并行 + 顺序逻辑

alt text

可视化优势
  • 分组组织 - 为大型流程提供颜色编码的分组
  • 实时验证 - 连接类型检查(绿色=有效,红色=错误)
  • 撤销/重做支持 - 完整的历史系统(Ctrl+Z/Y)
  • 运行时调试 - 播放模式下活动节点会高亮显示

⚡ 类型安全、零反射性能

Unity的泛型序列化设计存在缺陷。我修复了它。

问题所在

// ❌ Unity无法序列化这个
[SerializeField] private GameEvent<PlayerData> onPlayerDataChanged;

我们的解决方案

// ✅ 自动生成的具体类
[GameEventDropdown] public PlayerDataGameEvent onPlayerDataChanged;

// 生成的代码(自动):
[Serializable]
public class PlayerDataGameEvent : GameEvent<PlayerData> { }

性能优势:

  • 🚀 表达式树编译 - 条件在启动时编译为委托(无运行时解析)
  • 🚀 无反射成本 - 直接方法调用,而非 Invoke()
  • 🚀 原生Inspector支持 - 完全兼容 UnityEvent<T>
⚙️ 代码生成工作流
  1. 选择类型 - 在Creator窗口中选择你的自定义类型
  2. 生成 - 点击"Generate"创建具体类
  3. 编译 - Unity自动编译新代码
  4. 创建 - 现在你可以为自定义类型创建事件了

时间投入: ~10秒。收益: 终身类型安全。


功能特性总览

⚓ 核心架构

特性描述
基于资产的事件ScriptableObject架构,具有 GUID标识——引用在重命名和文件移动后仍然有效。
全面的泛型支持原生支持 GaneEvent<Void>GameEvent<T> 和源感知的 GameEvent<TSender, TArgs>
多数据库系统支持多个数据库的模块化组织,具有 动态加载健康检查 功能。
分类系统基于字符串的分类,用于在大型事件库中进行高效的模糊搜索过滤。
自动静态重置在编辑器播放模式下自动清除静态缓存,以防止数据污染。

🧠 高级逻辑与流程

特性描述
表达式树零反射 逻辑评估;条件在运行时编译为高性能委托。
可视化逻辑构建器无需代码即可构建复杂的 嵌套AND/OR逻辑 和动态属性比较。
混合执行在一个图表中无缝混合并行 扇出触发器 和顺序 阻塞链
参数转换器动态提取并传递特定对象属性作为流程节点之间的参数。
精细流程控制每个节点的延迟、异步/协程等待、循环计数和条件执行门控。

🎧 监听与绑定

特性描述
可视化绑定在Inspector中拖放式 UnityEvent连接,带有可视状态标记和类型安全。
优先级监听器基于整数的排序,确保关键系统在标准UI/音频监听器之前响应。
条件监听器内置 谓词支持——仅在满足特定逻辑条件时触发回调。
持久化监听器原生支持在场景转换期间保持活动的 跨场景监听器
动态运行时API完整的编程控制,用于注册或注销监听器并管理 任务句柄

📊 工具与调试

特性描述
仪表板与向导用于 批量操作 的现代UI和用于快速事件创建的模糊匹配向导。
代码自动化三模式代码生成(基础/自定义/Sender),带有自动编译管线集成。
引用查找器场景范围扫描器,精确定位哪些组件引用了特定事件资产。
运行时监控器实时分析 执行时间(平均/最小/最大)、监听器计数和 GC分配
自动化树活动触发器和链式层次结构的实时可视化工具,用于调试复杂逻辑流程。

性能特征

来自生产构建的实际指标:

场景性能备注
事件触发(0个监听器)~0.001ms几乎无消耗
事件触发(10个监听器)~0.02ms无GC分配
条件评估~0.003ms表达式树编译
流程节点执行~0.05ms包含协程开销
监控窗口(100个事件)~0.3ms仅编辑器,无运行时成本
生产就绪

已在发布的游戏中测试,包含 500+事件 和跨场景的 10,000+监听器。零性能退化。


🗺️ 导航路线图

此地图提供了系统文档的完整概览。使用下表快速跳转到您需要的特定功能或教程。

推荐的学习路径

🏁 1. 介绍

事件即资产架构的基础设置和核心理念。

页面描述
项目结构理解目录布局、文件夹保护和模块化组织。
安装初始化插件并设置自动静态重置管线。

💎 2. 可视化工作流

将不可见代码转化为有形可视化仪表板的管理工具。

页面描述
系统仪表板基于资产的工作流和GUID身份系统概览
数据库与流程图处理多数据库和多流程图设置以及数据库健康维护
编辑游戏事件使用仪表板进行批量编辑、搜索和分类
创建游戏事件使用模糊搜索批量向导快速生成事件资产
配置游戏事件掌握带有可视状态标记和类型安全的Inspector绑定
触发游戏事件学习如何调用事件并使用内置GameEventDropdown属性增强Inspector
查找游戏事件扫描场景以定位组件级事件依赖关系。
可视化条件树学习如何通过条件树配置控制事件动作的逻辑执行

🕸️ 3. 流程编排

使用节点可视化和构建复杂的多步骤逻辑序列。

页面描述
节点编辑器管理GraphView画布、分组和基于快照的撤销/重做
节点连接器混合执行模式的规则和实时连接验证
节点行为配置节点级延迟、循环和参数转换逻辑
高级逻辑模式构建无代码嵌套逻辑组和条件执行门控

💻 4. 脚本与API

开发者的高性能C#集成和生命周期管理指南。

页面描述
触发与调度编程式触发、延迟执行和任务句柄管理
监听策略实现优先级、持久化和源感知(Sender)监听器
编程式流程使用基于表达式树的谓词实现零反射逻辑过滤
最佳实践清晰解耦和防止数据污染的架构技巧
API参考所有核心类和属性的详细技术文档

🛠️ 5. 工具与支持

专业生产环境的自动化和监控实用工具。

页面描述
代码生成与清理使用三模式生成器和编译管线自动化
运行时监控器实时性能分析、深度日志记录和警告系统
社区与支持访问更新、报告错误和获取技术支持

📚 6. 示例

涵盖从基础到高级API使用的每个场景的实用即用场景。

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(快速开始),然后探索 可视化工作流 部分,了解编辑器工具如何简化您的开发。