帧同步游戏浅谈

帧同步是游戏中常用的同步方式之一,我们熟知的《王者荣耀》战斗过程中就是用的帧同步。

帧同步的原理是什么呢?在我看来,帧同步,其实就是保证不同客户端在相同的帧做相同的操作,一场游戏从开始到结束,每个客户端都跑了相同的帧数,最终都得到相同的结果。这里需要注意:帧同步,同步的是玩家操作,比如某个玩家在第2000帧的时候放了一个技能,那么这个操作需要同步到其他客户端,其他客户端也在2000帧的时候做这个操作,至于技能对周边造成多少伤害,需要由客户端来计算。

帧同步的另一个特点:计算任务放在客户端。客户端逻辑就像是一个数学公式,从游戏开始不断 有变量(玩家操作)输入,直到客户端计算逻辑发现游戏结束。对于每个端,相同的计算逻辑,保证相同的输入,必然会有相同的结果。

帧同步实现细节:
  1. 如何保证一个操作在相同的帧下执行?

服务器充当游戏的裁判,当一个客户端有一个操作的时候,这个操作是多少帧由服务器来判定。那么游戏在一开始的时候,服务器需要模拟客户端的帧率来运行,比如客户端以60帧的速率更新游戏逻辑,服务器也以相同的帧率跑,并且每一帧记录当前运行到了第几帧。当客户端有一个操作的时候,客户端将这个操作发送给服务器,服务器给这个操作设置当前是多少帧(服务器帧),然后转发这个操作给当前游戏的所有客户端,客户端收到服务器转发的操作之后,按照操作中设置的帧,在客户端运行到那一帧的时候去执行这个操作。

这里有个问题,客户端需要比服务端跑的慢,也就是客户端接收到的来自服务端的操作帧都应该大于当前客户端跑到的帧数,只有这样客户端才有机会执行这些操作,否则,当客户端跑到第2000帧的时候,收到一个1999帧的操作,此时如果没有逻辑倒退机制的话,就要漏掉这个操作了。而其他客户端有可能刚好执行了这个操作,那么最终的结果就是各个端不一致了。

  1. 如何保证客户端永远跑在服务端的后面?

除了客户端的操作帧之外,增加一种同步帧,同步帧以一定频率由服务器发送给客户端。

服务端发送同步帧给客户端,客户端运行每一帧的时候都去检查本地帧数和服务端发送过来的同步帧。当客户端帧数等于服务端同步帧时,客户端停止逻辑更新,等待服务器最新同步帧的到来。这样就保证了客户端本地帧小于等于服务端的帧,也就保证了客户端收到的所有服务端转发的操作指令帧在客户端本地帧之后。

  1. 服务器的同步帧应该以什么样的频率发送?

假设服务器按照客户端60帧的频率发送同步帧,那么客户端和服务器必须保证完全相同的速度运行。也就是说客户端跑了第一帧,那么下一帧跑到时候,服务端的第二帧的同步帧就必须同步到客户端才行,服务端和客户端要保证完全一致的节奏。这种情况下,任何一帧的网络波动都会导致同步帧不及时,客户端逻辑就要卡住。

那么同步帧设置多大合适?假设我们设置同步帧为每隔5帧一个。当游戏刚开始,客户端帧数为0,服务器给客户端的同步帧为0,此时游戏处于暂停状态,等第5帧的时候,服务器发送同步帧到客户端,客户端发现本地还是第0帧,然后开始跑,正常情况下当客户端跑到第5帧的时候,服务端发送第10帧的同步帧到客户端。此时客户端又可以继续跑了。

由于受网络抖动影响,如果每一帧都和服务端同步的话,任何一帧的突然延迟都可能导致客户端逻辑卡住。而如果每5帧一个同步帧的话,在5,10,15,这些这些帧数下出现同步帧延迟到来才可能导致客户端逻辑卡住。相比较,每隔5帧的同步方案,更能容忍网络波动。

实际上同步帧发送频率越小,对网络波动的容忍度越好。即服务器每隔10帧,或者15帧发送同步帧,会使客户端受网络影响而卡住的情况更少。

同步帧发送频率也不能太小,如果太小的话,就会导致延迟增大,由上面每隔5帧发送同步帧的例子可知,当服务器跑到第5帧的时候,客户端才开始从第1帧跑,因此,客户端和服务端因为同步帧的原因,会有同步帧大小的延迟。当客户端在第1帧有一个操作的时候,发送操作到服务器,服务器可能已经跑到第7帧了,那么这个操作就只能在第7帧执行。站在玩家体验角度来看,第1帧玩家释放一个技能,要等到第7帧才可以执行,这就产生了延迟。因此同步帧间隔也不能太大,太大就会导致延迟增大,影响玩家游戏体验。

  1. 断线重连问题

当游戏过程中玩家掉线时,由于与服务器失去联系,客户端可能会漏掉其他玩家的操作指令,那么当重新连接到服务器时,需要请求漏掉的所有操作指令,客户端将这些操作指令快速执行一遍就可以到达最新的状态,以后就回到正常游戏状态了。

这里有一点是需要客户端和服务器都做的,记录玩家操作。对于客户端来说,记录玩家操作,以便断线重连的时候只向服务器请求断开连接之后的操作,这样能减少请求数据量,缩短玩家进入正常游戏状态的时间。对于服务器而言,记录玩家操作也是为了断线重连,不仅仅在游戏中断开重连,还有一种情况是玩家退出了游戏,那么当玩家再次进入游戏时,客户端之前保存的操作指令都已经不在了。由于服务器记录了所有操作,就可以全部发送给客户端,客户端快速跑完所有操作指令,就可以到达游戏的最新状态了。

  1. 结果演算

对于帧同步游戏,客户端状态是实时计算出来的,那么游戏结果也是由客户端算出来的,当客户端计算得到游戏结束,那么本场游戏就结束了。如果游戏逻辑没问题,对于一场游戏而言不同客户端都会得到相同的结果。为了防止玩家通过各种手段作弊,导致游戏结果和正常逻辑运行的结果不一致,就需要服务器也能演算一遍游戏,当服务器演算结果和客户端结果一致时,那么我们才可以相信客户端结果。

所以服务端记录的所有操作还有一个作用,就是计算游戏结果的正确性。

然而每场战斗都需要服务器计算的话,如果战斗比较多的话服务器的计算压力会很大。其实对于多人游戏,可以通过客户端投票的方式来减少服务端的计算。比如:有4个玩家一起进行同一场游戏,在游戏的某一时刻,其中一个客户端通过计算发现游戏结束,该客户端将游戏结算结果发送给服务器,理论上其他三个客户端也会在这一时刻发现游戏结束,同样将结算结果发送给服务器。假设没有玩家作弊,那么服务器收到的四个计算结果都应该是一样的,此时服务器就可以判定该结算结果有效,并通知客户端游戏结束。假设有一个玩家作弊,那么结算结果就是1:3的情况,三个客户端的结果是一样的,按少数服从多数原则,服务端也可以以那三个相同的结果作为判定标准。以上两种情况服务器都不需要计算,就能判定最终的游戏结果。如果出现2:2的情况,那么服务端就无法判定哪边才是正确的结果,此时才需要服务端进行结果演算,最后以服务端的结果为准。这种投票方案可以大大减少服务器的计算量,同时客户端也不用等待服务器端计算结果,对玩家来说体验更好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值