转载,一个老鸟实时动作游戏的心得

来源:互联网 发布:黑巧克力推荐知乎 编辑:程序博客网 时间:2024/04/28 17:29

和MMORPG不同,实时动作型网络游戏追求操作的响应要求极高(<150ms)。
动作型网络游戏的制作人希望做到单机游戏的体验,网络游戏的服务。
 
  网络指令在多客户端间的同步算法,从原理上来说,围绕两种特性的取舍而定:
  * 牺牲局部实时性:某程度的互等待,保证各客户端间指令集在指定时间段一致。
  * 牺牲局部一致性:容许客户端本机先行模拟,等待后续指令到达纠正。(DR)

  网络的存在导致鱼与熊掌不可兼得,所以现在市面上的动作网络游戏都有
如下的妥协和折衷实现:
  * 在客户端本机上算大量关键运算来保证手感
  * 玩法上对直接进行的决定性互动的要求不高
  * 接受时不时网络延迟导致等待的缺点来维持复杂精确的玩法
  * 策划维持可玩性的底线下对一些一致性的要求求减低
 
  实时性需求非常高的网络游戏,舍是一种关键艺术。
  FPS,赛车,RTS,泡泡堂/QQ堂,模拟器联网等类型的网络游戏在一定程度上
都有以上的一个或多个取舍抉择。

---------------------------------------------------------------------

  在很多实时同步的网络游戏中,都用到UDP而不是MMORPG中的TCP进行
非关键消息的同步(更有些赛车,泡泡堂类的游戏直接起用p2p网络互联),
非关键消息在玩法上允许丢包,可以对物体状态做客户端预测来补偿,
所以UDP比TCP在这种情况下更合适。Dead Reckoning是常用的客户端
预测的技术,而更细节的客户端预测对不同类型的游戏而言有不同的扩展。
这方面的技术在之前的HalfLife / Quake3 / CounterStrike等UDP中心
服务器做动作认证的FPS游戏中应用得比较成熟。

  虽然觉得真正的p2p网状互联的动作同步不适合网游(不一致性和外挂都很严重),
但观察了几个游戏后相信有一些游戏是用网状p2p的,顺便了解一下原理。
  之前没了解过p2p体系的同步知识,所以先查阅了一些比较容易找到的paper,
所描述的分布式状态同步算法大致有如下几种。


---------------------------------------------------------------------

Lockstep Synchronization

  最直观同步方案:任何peer的action要得到其他所有peer的同意才能发起。
  见下图:
 
   
 
  如果使用非网状的p2p模型,提供peer master来做统一状态运算,
  那lockstep模型便成为严格的帧同步模型,这是大多RTS,模拟器联网,
以及一些提供建主机后连接的休闲动作游戏采用的同步模型;通过频繁
对时,便可以像编写串行单机指令一样来进行多个peer的事件指令同步。

  lockstep原是监狱用语,指犯人列队步行时的同步串链式行进,非常形象。
最初并非设计用于游戏,而是军方的军事互动仿真程序。IEEE DIS标准指出:
100-300ms的双程总延时,对军事性互动仿真模拟是可接受的。而根据一些统计,
第一人称射击游戏中的玩家双程延迟普遍在50-300ms的区间内。
而如果玩家都在一个LAN内进行p2p连接通信,双程延迟可能控制在20ms以内。

 优点:简单易实现,不会出现任何的不一致性。
       在延迟小(round-trip < 100ms)且稳定的环境下非常合适。
       在实时性要求不高的玩法(比如回合制玩法)中也非常合适。
 缺点:游戏节奏受最慢的peer影响巨大。一人卡机,所有人受影响。
       恶意的peer可以用伪造大延迟的方式来获得好处,从而破坏游戏公平性。

---------------------------------------------------------------------

Bucket Synchronization

  见下图:
 

  原paper很长,这里只按照个人理解编排步骤:
  (原文是彻底分布式的网状p2p,为方便理解,下面将player B称为peer master,
并假设它负责对时任务,以省掉NTP对时系统的理解过程)

1. 设定最大容忍延迟值为 PlayoutDelay(如120ms)。
   PlayoutDelay为:peer master执行指令N的时刻 - 远程peer的指令N发出时刻所对应的bucket时间段起始时间
2. 设定游戏时间轴上每隔BucketFrequency(如40ms)归一个新bucket来存放动作指令。
3. 开始游戏前,peer master发送对时命令给所有peer进行对时。
4. 因为peer master知道所有peer的平均延迟 AvgLag,那它执行步骤3后,
   延迟 AvgLag 时间后,开始游戏逻辑。
5. peer master自身发出的操作指令,虽然不需要经过网络,但也需要强行延迟
   投递到Ti对应的bucket中,其中:
      Ti = 当前时刻所属bucket时间段的起始时间 + PlayoutDelay
6. 如果peer master接到一个动作指令,但:
   peer master当前时间 - 动作指令携带的发送时间 > PlayoutDelay
   那peer master会直接丢弃这个动作指令(也就是将超时到达的指令当作无效)
7. 如果peer master接到的动作指令不超过上述6中描述的范围,那会把这个指令
   放入Ti所对应的bucket中,其中:
    Ti = 指令包携带的发送时间戳所在的bucket时间段起始时间 + PlayoutDelay
8. 每个bucket对应的时间段末端,peer master执行这个bucket中所有的指令,
   将结果状态更新到画面。
9. 因为有网络的存在,可能某些bucket中没有指令,原版MiMaze游戏实现是不处理。
   但paper中提供了基于Dead Reckoning的预测状态显示方法。
10. 游戏过程中,peer master以某种时间间隔作频率进行各peer对时,
   保证将各peer机器时间的误差控制在一个可接受范围内。


  优点:不依赖最慢peer来决定游戏流畅度。流畅度是维持在平均预定义水平的。
  缺点:对超过MaxLag的指令做丢弃。除了原paper中的3D吃豆人迷宫式游戏这种
        经过特殊剪裁的游戏,动作游戏对延迟玩家的操作做丢弃,似乎很难想象。

---------------------------------------------------------------------

TimeWrap Synchronization

  个人觉得是一个比较理想化的同步算法。对很多情况都有过度的假设。
它是一个基于全局状态支持回滚(rollback)的同步算法。
  简言之,就是对每个操作指令的执行后保存一个全局状态快照(snapshot),
各个peer按照自己的预测先行显示,但在发生一致性冲突的情况下,
回滚到上一个全局状态,并重新将指令序列在基于回滚后的快照的基础上再
执行一次,以获得正确的当前全局状态。 

---------------------------------------------------------------------

Trailing State Synchronization

  对TimeWrap Synchronization的一种改进。TimeWrap方案中建立snapshot是
以指令数量(1或少量几个指令)间隔为单位;而TSS方案则以某种延迟值(100ms)
间隔为单位对游戏做snapshot(比如100ms前做一个,200ms前做一个...)。
当发生一致性冲突时,寻找最远需要开始计算的snapshot,并将该snapshot到
现在为止的时间内的指令重新执行,得到正确的最新全局状态。

---------------------------------------------------------------------

参考文章:
<<Minimization of Latency in Cheat-Proof Real-Time Gaming by Trusting Time-Stamp Servers>>
<<End-to-end transmission control mechanisms for multiparty interactive applicatins on the Internet>>
<<Dead Reckoning: Latency Hiding for Networked Games>>
<<An Efficient Synchronization Mechanism for Mirrored Game Architectures>>

---------------------------------------------------------------------


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/akara/archive/2010/09/15/5885037.aspx

原创粉丝点击