网络游戏的对时以及同步方案
北京中新创科技有限公司
2011/12/26 12:33:09>> 进入商铺 大多数实时网络游戏,将server的时间和client的时间校对一致是可以带来许多其他系统设计上的便利的。这里说的对时,并非去调整client的os中的时钟,而是把gameclient内部的逻辑时间调整跟server一致即可。
一个粗略的对时方案可以是这样的,client发一个数据包给server,里面记录下发送时刻。server收到后,立刻给这个数据包添加一个server当前时刻信息,并发还给client。因为大部分情况下,gameserver不会立刻处理这个包,所以,可以在处理时再加一个时刻。两者相减,client可以算得包在server内部耽搁时间。
client收到server发还的对时包时,因为他可以取出当初发送时自己附加的时刻信息,并知道当前时刻,也就可以算出这个数据包来回的行程时间。这里,我们假定数据包来回时间相同,那么把server通知的时间,加上行程时间的一半,则可以将client时间和server时间校对一致。
这个过程用udp协议做比用tcp协议来的好。因为tcp协议可能因为丢包重发引起教大误差,而udp则是自己控制,这个误差要小的多。只是,现在网络游戏用tcp协议实现要比udp有优势的多,我们也不必为对时另起一套协议走udp。
一般的解决方法用多次校对就可以了。因为,如果双方时钟快慢一致的情况下,对时包在网络上行程时间越短,就一定表明误差越小。这个误差是不会超过包来回时间的一半的。我们一旦在对时过程中得到一个很小的行程时间,并在我们游戏逻辑的时间误差允许范围内,就不需要再校对了。
或者校对多次,发现网络比较稳定(虽然网速很慢),也可以认为校对准确。这种情况下,潜在的时间误差可能比较大。好在,一般,我们在时间敏感的包上都会携带时间戳。当双方时间校对误差很小的时候,client发过来的时间戳是不应该早于server真实时刻的。(当时间校对准确后,server收到的包上的时间戳加上数据包单行时间,应该等于server当前时刻)
一旦server发现client的包“提前”收到了,只有一种解释:当初校对时间时糟糕的网络状态带来了很多的时间误差,而现在的网络状态要明显优于那个时候。这时,server应该勒令client重新对时。同理,client发现server的数据包“提前”到达,也可以主动向server重新对时。
一个良好的对时协议的设定,在协议上避免client时间作弊(比如加速器,或者减速器)是可行的。这里不讨论也不分析更的利用游戏逻辑去时间作弊的方式,我们给数据包打上时间戳的主要目的也非防止时间作弊。
校对时间的一般用途是用来实现更流畅的战斗系统和位置同步。因为不依赖网络传输的统一时间参照标准可以使游戏看起来更为实时。
首先谈谈位置同步。
好的位置同步一定要考虑网络延迟的影响,所以,简单把entity的坐标广播到clients不是一个好的方案。我们应该同步的是一个运动矢量以及时间信息。既,无论是client还是server,发出和收到的信息都应该是每个entity在某个时刻的位置和运动方向。这样,接收方可以根据收到的时刻,估算出entity的真实位置。对于server一方的处理,只要要求client按一个频率(一般来说战斗时10Hz即可,而非战斗状态或player不改变运动状态时可以更低)给它发送位置信息。server可以在网络状态不好的情况下依据zui近收到的包估算出现在player位置。而client发出的每次player位置信息,都应该被server信任,用来去修正上次的估算值。而server要做的只是抽查,或交给另一个模块去校验数据包的合法性(防止作弊)。
在server端,每个entity的位置按10Hz的频率做离散运动即可。
client因为涉及显示问题,玩家希望看到的是entity的连续运动,所以处理起来麻烦一点。server发过来的位置同步信息也可能因为网络延迟晚收到。client同样根据zui近收到的包做估算,但是再收到的包和之前已经收到的信息估算结果不同的时候,应该做的是运动方向和速度的修正,尽可能的让下次的估算更准确。
关于战斗指令同步,我希望是给所有战斗指令都加上冷却时间和引导时间,这正是wow的设计。这样,信任client的时间戳,就可以得到client准确的指令下达时间。引导时间(或者是公共冷却时间)可以充当网络延迟时间的缓冲。当然我们现在的设计会更复杂一些,这里不再列出。对于距离敏感的技能,例如远程攻击和范围魔法,我们的设计是有一个模糊的miss判定公式,解决距离边界的判定问题。
这里,server对攻击目标的位置做估算的时候,可以不按上次发出包的运动方向去做位置估计,而选择用zui有利于被攻击者的运动方向来做。这样,可以减少网络状况差的玩家的劣势。
对于PVE的战斗,甚至可以做更多的取舍,达到游戏流畅的效果。比如一个网络状态差的玩家去打npc,他攻击npc的时刻,npc是处于攻击范围之内的。但是由于网络延迟,数据包被server收到的时候,npc已经离开。这个时候server可以以client的逻辑来将npc拉会原来的坐标。
虽然,这样做,可能会引起其他玩家(旁观者)client上表现的不同。但是,网络游戏很多情况下是不需要严格同步的。在不影响主要游戏逻辑的情况下,player的手感更为重要。
:王