帧同步技术(一)

关于帧同步技术原理及实现方案网上已经有非常多的文章介绍了,但做《月夜狂想曲》的帧同步战斗时还是有遇到很多具体的细节问题,也做了很多相关处理,在这打算分两篇文章记录一下。第一篇主要讲客户端如何保持一致性,会遇到哪些问题以及怎么处理。第二篇主要讲通过哪些改进可以让帧同步有更好的游戏体验。

帧同步的原理是,服务器只负责收集指令,然后以恒定帧率(例如30帧1秒)转发指令,真正的游戏逻辑由各个客户端各自计算,客户端要等到服务器派发的指令才能推进逻辑,没有收到指令时逻辑是暂停的(LockStep)。帧同步最重要的是确保各个客户端在不同硬件不同平台下各自计算游戏逻辑结果都是一致的。在Unity中为了达到这个目标,我们需要解决以下问题:

随机数:Unity自带的随机数因为有可能会被物理系统,粒子系统,UI系统,第三方组件等各种模块使用,我们是无法保证他在不同客户端下每次都能取到统一的随机数的。这就需要我们自己实现一套自己控制的随机数发生器,关于如何实现随机数的算法,之前写过一篇文章介绍《随机数生成算法》。在有可控的随机数发生器后,我们需要查找项目中所有用到随机数的地方,判断该流程是逻辑相关需要被统一接管的,还是表现相关可以由各个客户端自由决定的,从而使用不同的随机数发生器。 目标就是确保逻辑相关的流程下在各个客户端下都能取到同样的随机数。

Continue reading

服务器调度频率问题

最近在做帧同步的PVP时遇到一个问题。在当初设计的帧同步方案中,服务器是以恒定每秒30帧的速率向客户端广播当前的双方的操作信息的。客户端也是按照每秒30帧的速率来处理这些信息,从而推进游戏逻辑的。这个方案双方速率一致是很重要的,如果服务器快了,客户端就要快进,如果服务器慢了,客户端就要等待。服务器方面我们是通过设置一个定时器来驱动这一部分逻辑的,这个定时器的间隔就是1000 / 30 ms,取值33或者34在个人电脑(Win7)环境下,都是能正常1秒能执行30次的。但部署到服务器环境(WinServer2012)下,定时器间隔无论设置33ms还是34ms,最终1秒都只能触发21次左右,如果把值设得更小,例如30,就会变成1秒执行32次,但无论设什么值都无法准确的1秒执行30次。

一开始在外网虚拟的服务器下发现这个问题,以为是虚拟机导致的,后面换到自己的物理服务器上(WinServer2008) 还是有这个问题,就开始考虑是不是服务器底层调度有问题,但后来通过一些测试发现是系统的问题。

Continue reading