不久前,我写过关于如何作为单独开发者来维持一个规模化的城市建造游戏的可行性 - 简而言之,主要是细节层次,百万名公民中,大部分以统计群体的形式而非全面的代理人存在,只有当他们靠近摄像机时才会变成个体。几个人在评论中提出了很好的问题,关于我略过的部分,所以我想深入探讨一下它让我付出的最大的自律:决定性。

我遵循的规则是:相同的启动种子加上相同的输入序列必须产生每次运行的字节完全相同的世界。不是相似。完全相同。如果你从来没有为此而建造过,听起来像是一个好处。它不是。它使得保存可信赖(保存只是种子加上输入日志),它使得重放成为可能,还有它使得我能够复制一个错误而不是盯着一个我再也拿不回来的世界。 如果我以后添加网络功能,锁步依赖于它。

这是它实际上每天都会给你带来的什么。

浮点数是第一个会咬你的东西。相同的浮点运算在不同的CPU上,编译器设置上,甚至有时在不同运行上会给出不同的结果。因此,对于任何穿越系统或地图区域的东西,我改用了定点运算 - 底层是整数,带有一个固定的小数部分。虽然在原始性能上更慢,但在任何地方都是相同的,这就是全部的重点。浮点数只允许在一个计算中使用,计算结果必须在任何人看到之前以定点数形式进行舍入。

随机性是第二个。不能从任何地方调用一个全局的随机函数,因为一旦你并行化,发生顺序就不再保证了。所以,有一个种子生成器,它分发了命名的子流 - 交通系统有自己的,人口系统有自己的 - 因此两个系统绘制随机数不能干扰彼此的序列。

多线程是第三个,也是最难的。并行运行系统是如何达到性能目标的,但并行性是非决定性的 - 线程完成顺序是你控制不了的。自律的规则是:在一个并行阶段中,只有一个线程允许写入一个给定块的数据,而所有写入都必须在下一个阶段开始之前在一个固定屏障中提交。并行性买到了速度;屏障买回了决定性。

元教训,实际上也是我发表的原因:决定性在一开始就要决定,或者不做。决定性不是你可以在后来加上的东西。它影响你的数学类型,RNG,线程模型,保存格式 - 它们都承载了它。如果有任何机会你会想要可靠的保存,重放,或者网络功能,提前支付税金,而代码库还小。

上次是关于什么,这次是关于如何。继续下去,国度规模的寻径(收缩层次结构而非平常的A*)可能是下一个,如果有兴趣,或者建造-vs-购买的ECS决策。告诉我有用的是什么。

(同样,之前一样:我是开发者,游戏的Civitas,不在正文中链接它。很高兴在评论中加入它,如果有人想跟随建造。)