FPS游戏原理漫谈:玩家延时与服务器同步

>>>  創業先鋒 眾人拾柴火焰高  >>> 簡體     傳統


  在在FPS游戏中玩家延时都不一样的情况下是怎样做到游戏的同步?知友“周恺华”对此给出较为充实的回答,有兴趣了解这方面知识的玩家可以通过下面的回答来一窥究竟:

  声明:下面会大量使用CSGO作为例子,因为Valve在多人游戏的网络通信方面做得较好,可以当做一个典型来分析。

  多人竞技游戏中客户端和服务器的互动

  游戏中所有的逻辑判定都是由服务器完成的,客户端只负责发送请求和接收服务器的反馈,并把反馈具象化。拿CSGO做例子,玩家A拿着AK瞄准了玩家B的头开了一枪,那么玩家A的客户端会向服务器发送一个数据包,里面包含了谁(玩家A)拿着什么武器(AK)从什么位置(玩家A在地图上的坐标)向什么方向(角度)开了一枪。服务器收到后进行判定,这一枪的伤害会经过玩家B的头部模型,判定为爆头伤害,数值为XX,判定玩家B死亡。服务器再向所有玩家的客户端通信,更新当前游戏状态,其中包括玩家A用AK爆头击杀了玩家B,也会包括其他信息,比如玩家们的位置等等。玩家A收到通信后显示击杀了玩家B,玩家B则会收到被击杀的信息。

  接着讲一个概念,叫服务器的通信频率(tick rate)。事实上服务器不是百分百实时地向玩家通信来更新游戏状态的,那样需要的计算量很大,同时对网络带宽的要求也会高的不现实,因此服务器会以一定的频率来进行通信。

  CSGO在娱乐模式下通常采用60Hz的频率,也就是说每过1/60秒玩家的客户端就会收到一次新的信息。如果回到上面那个例子,那么实际情况应该是:玩家A拿着AK瞄准玩家B的头开一枪,你的客户端会向服务器发送一个数据包,服务器接收后进行判定。判定完成后等待至下一次通信,再向所有玩家更新游戏状态。也就是说游戏过程其实是一个离散的过程而非连续过程。


  如果玩家的Ping很大,服务器会怎么办?

  上面的例子都假设客户端和服务器之间的延迟无穷小,那么当玩家Ping很大的时候会发生什么的呢?

  假设玩家A与服务器之间存在100ms的延迟(单向,往返则是200ms),其他玩家的延迟忽略不计,服务器的通信频率足够大(频率不够大还会造成其他很严重的问题,这个放在后面讲)。玩家A在某一刻向服务器发送了一个请求(比如向前走),那么这个请求会在100ms之后到达服务器,服务器判定后返回结果,再经过100ms你的客户端会收到确认,服务器已经把你的位置向前移动了若干距离。假设客户端在没有收到任何服务器的更新前画面都不会变化,那么在这200ms内你就会觉得游戏“卡顿”。

  实际上很多游戏里中你会在这200ms里看到你自己是在向前走,其实那只是客户端“擅自”在绘制你前进的样子,这是一种延迟补偿策略,称为“客户端预测法”。即客户端能够大致预测游戏未来的走向,因此在接收到服务器更新前会把预测到的画面先绘制出来(比如移动、武器的开火效果、弹药计数的变化等)。客户端收到服务器通信后如果数据有出入则立刻纠正为服务器提供的数据。因此在延迟很大的时候玩家会发现“明明往前走了过了一会又瞬移回到之前的位置”的原因,或者是“明明开了好几枪而且也都显示了但过了一会弹药计数只减少了一点点”。

  既然扯到这里了那就认真的讲下延迟补偿策略(lag compensation),一般来讲补偿策略分服务器端和客户端两类,上面提到的预测法属于客户端一类,其他的客户端策略还有插帧法。所谓插帧法就是客户端会记录之前一次从服务器收到的信息,然后在接受到下一次通信的时候不立刻更新游戏画面,而是逐渐的更新画面(比如两次通信间玩家B移动了10单位距离,客户端会绘制玩家B以一定的速度移动了这10单位距离,而非立刻绘制玩家B瞬间移动了10单位距离)。插帧法的问题在于如果玩家并未沿直线运动且其直线路径中有本应不能通过的物体存在时(比如绕过一堵墙),客户端会绘制出该玩家穿墙而非绕过去的动作。

  服务器端处理延时同步常用的策略

  1、“眼不见为净”法,服务器不去补偿玩家的延迟是一个合理的做法,特别是当游戏内进行的事件非常多(想想《行星边际2》里面千人同图混战的情形)。浪费宝贵的服务器资源去补偿个别玩家的延迟是不明智的。这个策略的缺点很明显,就是玩家有可能会对游戏体验不满意。

  2、“倒带”法,采用倒带法的服务器会记录刚刚过去一段时间内(比如0.5秒)游戏内的所有信息。当一个有延迟的玩家(比如200ms)向服务器发送一个请求,那么服务器在处理这个请求的时候会调取0.2秒前游戏的状态然后进行判定,在把判定结果对所有客户端进行同步,如此一来该玩家的操作虽然有延迟但也能与他/她所看见的画面一致。该策略的最大问题在于它让不同延迟之间的玩家被迫体验较大的延迟。举个例子,假设游戏里击杀时间(TTK)足够小,玩家A(10ms延迟)和玩家B(延迟200ms)对射,两人都是空血(一次攻击即死),A比B先开火(时间差很小,比如50ms)。玩家A的次攻击很快(10ms后)就得到了处理并记录在服务器中,玩家B被判死亡。然而在200ms后玩家B的请求到达,服务器倒带0.2秒,此时玩家AB都未死亡,因此玩家B的攻击有效,玩家A也被判定为死亡。如果没有延迟,那么服务器应该会判定玩家B死亡,因此玩家B将无法攻击,玩家A应该存活。换句话说采用倒带法的服务器里如果有一个延迟很大的玩家将会拖累其他低延迟玩家的游戏体验。


文 / 周恺华 知乎


GameRes游资网 2015-08-23 08:47:48

[新一篇] 《每周一玩》第二十八期:全新西游夢 經典再啟航

[舊一篇] 小議關于游戲設計的各種理論是否有用
回頂部
寫評論


評論集


暫無評論。

稱謂:

内容:

驗證:


返回列表