我为我的游戏引擎构建了协程,但最后却没有使用它们

我为我的游戏引擎构建了一个生成器协程系统。它只有 122 行代码,并配有 12 个测试。它解决了回调地狱问题,让脚本看起来像是一条直线。

然后,我决定不在游戏逻辑中使用它。相反,我使用了有限状态机 (FSM)。

以下是原因。

大多数教程都忽略了生成器在实时游戏中的两个重大问题:内存和存档。

1. 内存压力

每当你对生成器调用 .next() 时,JavaScript 引擎都会创建一个新对象。该对象包含当前值和状态。

在以 60 FPS 运行的游戏循环中,这会产生持续的垃圾回收 (GC) 压力。我的引擎遵循“零分配”规则以保持性能稳定。而生成器打破了这一规则。它们在每一帧都会产生一系列微小对象。

2. 序列化问题

游戏需要存档和读档。你需要将当前游戏状态转换为数据,并能将其还原。

你无法序列化一个暂停中的生成器。它的状态存在于你无法访问的引擎内部插槽中。如果你尝试保存它,你会得到一个空对象或报错。

有限状态机则不同。状态仅仅是组件上的一个字符串。

  • 存档:将字符串写入磁盘。
  • 读档:读取字符串并告知 FSM 从该状态开始。

FSM 胜出了,因为它处理了专业游戏中最关键的两件事:性能和持久化。

如何选择:

逻辑是否在主帧循环内?

  • 否:使用生成器协程。它们非常适合加载资源或新手引导等一次性流程。
  • 是:问下一个问题。

状态是否需要在存档后保留?

  • 是:使用有限状态机。
  • 否:问下一个问题。

你是否在同时运行许多序列?

  • 是:使用有限状态机。
  • 否:使用生成器协程。

生成器并不是错误的选择。它们只是不适合用于“热路径 (hot path)”。可以将它们用于异步粘合逻辑,但游戏逻辑请使用 FSM。

Source: https://dev.to/grzott/i-built-generator-coroutines-for-my-game-engine-then-didnt-use-them-o3g