我终于完成了我的城市建设者Venusville的保存系统。

花了大约3个月。

我已经有了一个从我的第一款游戏继承过来的保存/加载库,所以我以为自己已经在一个不错的位置了。对象有ID,ScriptableObject状态可以正常序列化,我已经有了一个干净的 marshal/unmarshal管道来处理状态数据。

但事实上,城市建设者是一个完全不同的怪物。

真正的问题不是保存数据,而是正确地恢复一切

  • 预设
  • 依赖关系
  • 对象关系
  • AI状态
  • 第三方库,它们绝对不想合作

其中一个最大的变化是简化启动流程。现在加载保存和开始新游戏都发生在非游戏场景中,所以游戏场景只负责从ScriptableObject状态数据中恢复。

以前我依赖于预设的Start()函数和编辑器分配的新游戏设置数据,这些在保存/加载出现之前都正常工作。但是,依赖关系很快就变得不一致。

我最终引入了5个恢复阶段:

  1. 恢复核心对象(如人、建筑/室内/资源)
  2. 恢复依赖关系(之间的组件和子组件)
  3. 恢复关系(如人携带资源)
  4. 恢复行为树阶段1
  5. 恢复行为树阶段2

行为树部分尤其痛苦。

我使用的是一个很好的库,但它内部做了些很令人质疑的事情。例如,它会在我已经恢复它们之后清除共享变量引用GameObject。这种事情迫使我引入了一些丑陋的工作绕过系统,我必须缓存并在启用行为树之前恢复数据。

然后就出现了隐蔽的bug。

我有几个案例,数据存在两个地方而不是只有一个真实来源。例如,发起者和人都存储了相同的合同数据(如Atmos工厂的生产)。一开始看起来一切正常,但载入的游戏慢慢开始变得不正常。

这些是最糟糕的bug,因为它们是慢性炎症问题。副作用会在5-20分钟后出现,然后像病毒一样通过模拟传播。

总之。

我现在可以保存和加载城市建设者了。