Date: 16 Sep 2016
点对点模型。完全分布式模型,理论上可以不需要中央服务器,客户端之间可以直接通信。客户端之间的同步通常使用「帧同步模型」,这个模型把游戏进行的过程分一个一个的「回合」。每一回合客户端都需要把自己的行为发送给同时进行游戏的其他客户端,只有当自己发送的消息被其他客户端收到,并且自己也收到了其他客户端发送的同步消息后,才会根据这些同步信息进行游戏,然后进行下一回合,这就保证了每个客户端在信息上完全同步的。这样的一回合也叫做「游戏帧」,这个帧和游戏引擎中的帧并不是一个概念。
虽然这种模型保证了玩家信息的完全同步,但是也有它的缺点:
虽然这种模型有这些缺点,但是当今的很多RTS游戏还才用了这种模型,主要原因就是 RTS 游戏中游戏单位很多,如果要同步游戏中每个单位的信息的话,网络开销就太大,而同步玩家的指令则要有效率的多。
点对点模型由于需要客户端之间的相互通信,在网络不好的情况下会导致游戏变的很慢,所以一些对游戏速度要求很高的游戏类型(例如 FPS 游戏)中就不能够使用这种模型了。
1996 年,John Carmack 在 Quake 中使用了 C/S 模型来满足玩家网络对战的需求。在最初的实现中,客户端完全不运行游戏逻辑,它只负责两件事:
这种模型相对于点对点模型的优点是:
但是这种模型同样也有缺点,由于客户端没有任何游戏逻辑,玩家的任何操作都要通过服务器的计算后才知道,所以玩家的操作得不到及时的反馈,在网络情况糟糕的时候这种体验就更为明显。
为了减轻由于网络延迟带来的游戏不流畅,通常可以从两个方面入手:
所谓客户端预测就是在收到玩家的输入后,把输入的信息在传输给服务器的同时,客户端的游戏逻辑会直接处理玩家的输入无需等待服务器反馈(extrapolation),由于网络延迟的存在,客户端会领先于服务。为了防止作弊,游戏会把玩家本地输入产生的游戏指令在本地进行保存,然后与服务器传来的游戏指令进行比较,如果本地指令与服务器传来的指令不一致,则以服务器的指令为准,将游戏滚回到执行服务器指令的那个状态。
在 C/S 模型中,玩家之间的延迟永远是存在的,换句话来说在你自己的客户端上看到的其他玩家总是之前一段时间的玩家。以射击游戏为例,如果你的延迟很高,你要攻击的目标其实已经早已不在所显示的位置上了,而且如果射击命中的判定是在服务器上进行的话,你就会发现击中目标之后并没有效果,因为你的目标早已不在这个位置了。为了降低这种游戏体验上的不快,服务器在判定的射击时候并不是以目标最新的位置状态来进行判断的,而是以之前的一段时间的位置来判断,这样就等于减少玩家之间延迟,这就是服务器端的延迟补偿。
这部分的内容主要来自于一个《守望先锋》开发者这介绍这款游戏网络编程的视频,在这个视频中他们主要强调了两个原则。第一个原则:「满足射击者」,也就是在绝大数情况下是你能命中在本地客户端射击到敌人,这就意味着守望先锋在命中判定上依靠的是客户端,至于能有多少伤害要依靠服务器,这可也为服务器端判定攻击的有效性提供了可能;同时也很少会采取延迟补偿的方式来进行射击判定。另一个原则就是「高响应性」,这就是采用上面说的客户端模拟的方式来保证玩家的操作能得到快速的响应,当然他们也会使用服务器来验证玩家的行为是否合理。
同时,在这两个原则下也有一些例外,比如一些慢速的技能客户端则不会进行预测模拟而是完全和服务器同步,这就是快速响应下的特例,在这儿采用这种方式的原因我觉得主要是因为:首先,技能很重要,需要服务的确认;其次慢速技能即使采用完全和服务器同步也不会因为网络延迟在技能效果上产生很大的影响。满足射击者也有特例,比如一些角色的技能可以让他们免疫伤害,这时候命中伤害的判定就需要服务器的来确认了,而且在大多数情况下,只要玩家释放的技能,伤害的确认都是要服务器来进行的,因为技能对于玩家来说是很重要的。而且在满足射击者这一点上,他们还加入了一个延迟的上限,也就是说你命中了一个很久之前的游戏目标,这种命中也是无效的。总之,在「满足射击者」和「高响应性」两个原则下,为了更好的游戏效果他们还是会做一些特殊处理,特别是在玩家使用了技能的时候。
What every programmer needs to know about game networking
Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization