独自开发一款浏览器RTS游戏,网络同步采用锁步模式:每个客户端在本地模拟完全相同的世界,只有指令通过网络传输。这意味着整个系统建立在一个假设之上:每台机器永远进行逐比特一致的数学运算。

这个假设悄然崩塌了。两个客户端,相同的录像回放,相同的输入,却在战斗中途逐渐偏离——没有崩溃,没有报错,只是两个玩家慢慢看着不同的战局。追查到最后锁定了一行代码:桥接碰撞逻辑中的Math.hypot。原来底层数学库会根据操作系统不同,对最后一位进行不同的舍入。不是错误,只是不同,而当整个设计依赖精确一致性时,这种不同就是致命的。

修复方案:将所有模拟数学运算路由到自定义函数,并通过lint规则禁止直接调用标准库。路径查找同样用C++编译成WebAssembly运行,因为在此处逐比特一致性是唯一关键。

还有其他人开发确定性模拟时遇到过这种跨平台浮点漂移问题吗?很好奇大家如何在问题累积到玩家能察觉到之前就发现它。(如果作为背景参考,项目在batargon.com,浏览器RTS,美术由AI生成,代码是我写的。)