【帧同步】关于状态同步的经验分享

方案

低延迟环境下 比如国内,局域网情况下 写个同步那都不是难事 是个客户端看点书就会写了
难点在于 如何去处理 高延迟 以及及时响应的情况 我举个例子 fps或者tank游戏中 子弹和炮弹的射速是很快的 如果两边在对轰过程中 又碰到了 附近的建筑物或者树木 这时如果等服务器返回过来 表现上就有很大的差异 ( 子弹都飞过去了 树才炸开 粒子特效才播出来 这种情况是很难被玩家接受的 ) 所以我们需要在前端对行为进行预判 并在服务器数据返回后进行校验和有必要的回滚

  1. 对玩家自己的数据进行预测
  2. 对其它的玩家 仅同步服务器状态 不预测
  3. 玩家的操作 需要发送时间切片的ID 服务器对当前切片下玩家的状态进行处理 且要判定回滚
  4. 间隔一段时间来校验玩家与服务器中玩家的状态 存在差异时 回滚处理

在这里插入图片描述

帧预测

客户端预表现来优化响应,需要满足一个前提:(如果游戏世界具有足够的确定性(游戏邦注:即给定游戏状态和一组输入),那么结果是完全可预测的)。

即给定当前帧状态+当前帧输入,能够100%正确和到下一帧状态。
Client-Prediction 可能会带来 Server Data 覆盖 Client Data 导致的抖动问题。
在这里插入图片描述
上图中,正确的表现应该是 10->11->12,因为Server Data慢于Client-Prediction,所以实际表现是 10 -> 11 -> 12 ->11 ->12,产生了抖动。
解决方法是,给每个C->S包加上一个序号,当S->C时,带上最后处理的序号。

在这里插入图片描述
图中,当Client收到#1时,重复所有状态为服务器下发状态,并重新执行#2(进行预表现)。所以实际表现会是 10->11->12->12。

Dead Reckoning 算法。

	此算法用于状态同步下处理玩家的移动。可以缓解 high latency,并且降低带宽。

核心思想:本地模拟,发现差异过大时上传。
  在跑的过程中,玩家A有一个值在不停的记录着其真实坐标和在后台模拟运动的坐标的差值,当差值大于极限误差的时候,则计算出当前的速度S、方向O、速度A、位置,并广播给网络中其他所有节点。其他节点在收到这条消息之后呢,就可以用一些很平滑的移动把路人甲拉扯过去。
 此种方法下,依赖客户端模拟计算,玩家A可以任意的走动,当不一致时,上报位置。
 
 在没有收到PDU的时候,需要模拟对方的运动,DR提供了几种经典算法:

(1)位置1 = 位置0,就是保持不变
(2)位置1 = 位置0 + 速度 × (T1 – T0),相当于根据PDU中的数据,做匀速运动
(3)位置1 = 位置0 + 速度 × (T1 – T0)+ 1/2 × 加速度 × (T1 –T0)平方,比2)中多了加速度的方向

帧回滚

回滚逻辑,就是我们解决问题的方案。可以这样理解,客户端的时间,领先服务器,客户端不需要服务器确认帧返回才执行指令,而是玩家输入,立刻执行(其他玩家的输入,按照其最近一个输入做预测,或者其他更优化的预测方案),然后将指令发送给服务器,服务器收到后给客户端确认,客户端收到确认后,如果服务确认的操作,和之前执行的一样(自己和其他玩家预测的操作),将不做任何改变,如果不一样(预测错误),就会将游戏整体逻辑回滚到最后一次服务器确认的正确帧,然后再追上当前客户端的帧。

此处逻辑较为复杂,我尝试举个例子说明下。

当前客户端(A,B)执行到100帧,服务器执行到97帧。在100帧的时候,A执行了移动,B执行了攻击,A和B都通知服务器:我已经执行到100帧,我的操作是移动(A),攻击(B)。服务器在自己的98帧或99帧收到了A,B的消息,存在对应帧的操作数据中,等服务器执行到100帧的时候(或提前),将这个数据广播给AB。

然后A和B立刻开始执行100帧,A执行移动,预测B不执行操作。而B执行攻击,预测A执行攻击(可能A的99帧也是攻击),A和B各自预测对方的操作。

在A和B执行完100帧后,他们会各自保存100帧的状态快照,以及100帧各自的操作(包括预测的操作),以备万一预测错误,做逻辑回滚。

执行几帧后,A,B来到了103帧,服务器到了100帧,他开始广播数据给AB,在一定延迟后,AB收到了服务器确认的100帧的数据,这时候,AB可能已经执行到104了。A和B各自去核对服务器的数据和自己预测的数据是否相同。例如A核对后,100帧的操作,和自己预测的一样,A不做任何处理,继续往前。而B核对后,发现在100帧,B对A的预测,和服务器确认的A的操作,是不一样的(B预测的是攻击,而实际A的操作是移动),B就回滚到上一个确认一样的帧,即99帧,然后根据确认的100帧操作去执行100帧,然后快速执行101103的帧逻辑,之后继续执行104帧,其中(101104)还是预测的逻辑帧。

因为客户端对当前操作的立刻执行,这个操作手感,是完全和pve(不联网状态)是一样的,不存在任何delay。所以,能做到绝佳的操作手感。当预测不一样的时候,做逻辑回滚,快速追回当前操作。

这样,对于网络好的玩家,和网络不好的玩家,都不会互相影响,不会像lockstep一样,网络好的玩家,会被网络不好的玩家lock住。也不会被网络延迟lock住,客户端可以一直往前预测。

对于网络好的玩家(A),可以动态调整(根据动态的latency),让客户端领先服务器少一些,尽量减少预测量,就会尽量减少回滚,例如网络好的,可能客户端只领先2~3帧。

对于网络不好的玩家(B),动态调整,领先服务器多一些,根据latency调整,例如领先5帧。

那么,A可能预测错的情况,只有2~3帧,而网络不好的B,可能预测错误的帧有5帧。通过优化的预测技术,和消息通知的优化,可以进一步减少A和B的预测错误率。对于A而言,战斗是顺畅的,手感很好,少数情况的回滚,优化好了,并不会带来卡顿和延迟感。

重点优化的是B,即网络不好的玩家,他的操作体验。因为客户端不等待服务器确认,就执行操作,所以B的操作手感,和A是一致的,区别只在于,B因为延迟,预测了比较多的帧,可能导致预测错,回滚会多一些。比如按照B的预测,应该在100帧击中A,但是因为预测错误A的操作,回滚重新执行后,B可能在100帧不会击中A。这对于B来说,通过插值和一些平滑方式,B的感受是不会有太大区别的,因为B看自己,操作自己都是及时反馈的,他感觉自己是平滑的。

这种方式,保证了网络不好的B的操作手感,和A一致。回滚导致的一些轻微的抖动,都是B看A的抖动,通过优化(插值,平滑等),进一步减少这些后,B的感受是很好的。我们测试在200~300毫秒随机延迟的情况下,B的操作手感良好。

这里,客户端提前服务器的方式,并且在延迟增大的情况下,客户端将加速。

这里,我要强调的一点是,我们这里的预测执行,是真实逻辑的预测,和很多介绍帧同步文章提到的预测是不同的。有些文章介绍的预测执行,只是view层面的预测,例如前摇动作和位移,但是逻辑是不会提前执行的,还是要等服务器的返回。这两种预测执行(View的预测执行,和真实逻辑的预测执行)是完全不是一个概念的,这里需要仔细地区分。

帧同步和状态同步的区别

对于大部分游戏来说,两种同步方式都可以使用。但相比之下状态同步适用型更广,特别适合复杂度高,延迟要求高,玩家多的游戏,例如FPS,MMO等等。帧同步相对适合小兵很多,玩家少且固定,单局时间短,对打击感公平性要求高,追求一致性的游戏,例如格斗,运动,RTS,卡牌,MOBA等。

从技术角度来说,帧同步有一些技术限制,大量玩家战斗,随时进入退出,难以预表现等,而状态同步有更多的优化手段可以更好的降低延迟感。可以说用帧同步的一定能用状态同步,但反过来不成立。

当然帧同步也有自己的优势,实现成本相对简单开发比较快速(一套逻辑不太需要联调),在玩家较少小兵较多的情况下(由于只同步事件而非状态,所以网络传输的数据和游戏里的对象数量无关)服务器性能和带宽开销极低,甚至可以没有服务器(服务器可以完全不跑战斗逻辑只在需要反挂的时候跑),有点去中心化的意思。也非常适合一些单机游戏改成联网得游戏,非常适合中小公司(之前开发的一个MOBA游戏只有一个服务器同学)。

我们在选择的时候需要综合考虑游戏类型,未来需求,战斗时长,游戏模式,网络带宽,延迟响应,防作弊,开发成本周期和实力等因素来选用不同的同步方案,甚至混合使用。没有最好的技术只有最适合的技术

总结一下:

1、对于回合制战斗来讲,其实选用哪种方式实现不是特别重要了,因为本身实现难度不是很高,采用状态同步也能实现离线战斗验证。所以采用帧同步的必要性不是很大。

2、对于单位比较多的RTS游戏一定是帧同步,对于COC来讲,他虽然是离线游戏,但是他在一样输入的情况下是能得到一样结果的,所以也可以认为他是用帧同步方式实现的战斗系统。

3、对于对操作要求比较高的,例如MOBA类游戏有碰撞(玩家、怪物可以互相卡位)、物理逻辑,纯物理类即时可玩休闲游戏,帧同步实现起来比较顺畅,(有开源的Dphysics 2D物理系统可用 它是Determisti的)。

4、对于战斗时大地图MMORPG的,一个地图内会有成千上百的玩家,不是小房间性质的游戏,只能使用状态同步,只同步自己视野的状态。

5、帧同步有个缺点,不能避免玩家采用作弊工具开图。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极客柒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值