跳到主要内容

3 篇博文 含有标签「Flow Graph」

Event flow graph orchestration

查看所有标签

运行时构建事件流:当可视化编辑器不够用的时候

TinyGiants
GES Creator & Unity Games & Tools Developer

你的程序化地牢生成器刚刚造了一个有三块压力板和一个尖刺陷阱的房间。下一个房间是一个连接着锁门的拉杆谜题。再下一个是 Boss 竞技场,环境危害根据 Boss 的血量阶段激活。这些事件关系在编辑期一个都不存在。地牢布局取决于玩家 30 秒前输入的种子。

你怎么连接这些事件?

传统做法是写一个巨大的 switch 语句。每种房间类型手动订阅和取消订阅事件处理器。每种 AI 难度手动串联不同的攻击模式。每个 Mod 创建的内容手动解析配置文件并翻译成事件连接。"手动"就是问题所在 —— 每当拓扑在运行时改变,你就在重新实现事件连线逻辑。

可视化节点编辑器在处理设计期已知的流程时非常棒。但它们从根本上无法处理运行前根本不存在的流程。而越来越多最有趣的游戏系统恰恰就是事件图动态生成的那种。

并行还是顺序:每个事件系统都需要的两种执行模式

TinyGiants
GES Creator & Unity Games & Tools Developer

玩家死了。死亡音效和死亡粒子应该同一瞬间开始——没必要等一个完了再开始另一个。但屏幕淡出绝对必须在重生点加载之前完成。重生加载必须在传送之前完成。传送必须在屏幕淡入之前完成。

这就是并行和顺序执行同时存在于一个流程中,由一个事件触发。而尴尬的现实是:大多数 Unity 事件系统只给你一种模式。触发事件,所有监听器响应,完事。至于这些响应应该同时发生还是严格按顺序来?你自己想办法。

于是你就去解决了。用协程。用回调。用名为 _hasFadeFinished 的布尔值。不知不觉间,你搭了一个散落在六个文件里的临时状态机,包括未来的你在内没人能看懂。

看不见的事件链:你无法调试看不见的东西

TinyGiants
GES Creator & Unity Games & Tools Developer

玩家死了。死亡音效响了。布娃娃激活了。UI 弹出"你死了"。游戏自动存档。数据分析事件发出去了。重生倒计时开始了。六个不同的系统,全部在响应一个事件:OnPlayerDeath。但我的问题是——这些关系记录在哪?

不在你的代码里。不在项目管理工具里。不在任何图表里。它存在于一个地方:最初配置它的那个人的脑子里。如果那个人半年前离职了,那它哪儿都不存在。

这就是事件驱动架构的脏秘密。我们采用它是因为它解耦了系统。我们庆祝 AudioManager 不需要引用 UIManager 了。但我们从不谈代价:执行流变得不可见了。而不可见的东西,从定义上来说,就是没法可视化调试的。