方案

低延迟环境下 比如国内,局域网情况下 写个同步那都不是难事 是个客户端看点书就会写了
难点在于 如何去处理 高延迟 以及及时响应的情况 我举个例子 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. mtk 帧同步_【小松教你手游开发】【面试必读(编程基础)】网络游戏同步方式(帧同步和状态同步)...

    在做网络游戏的时候首先要做的是选择一种同步方式来使用,网上的文章都是说帧同步与状态同步的选择,但是又经常讲的模糊不清,我大概整理了一下,并且有一种我们现在项目用的网络同步方式 状态同步 状态同步就有好 ...

  2. 【网络同步】浅析帧同步和状态同步

    前言 谈到网络游戏,不可避免要谈到现有两种比较常见的网游同步技术:帧同步和状态同步 说到这两个名词,大家夸夸奇谈,都能讲上些许自己的见解,我反正啥也不懂 这篇文章就打算着重学习一下这两种技术的基础和原 ...

  3. 网络游戏同步方式(帧同步和状态同步)

    在做网络游戏的时候首先要做的是选择一种同步方式来使用,网上的文章都是说帧同步与状态同步的选择,但是又经常讲的模糊不清,我大概整理了一下,并且有一种我们现在项目用的网络同步方式 状态同步 状态同步就有好 ...

  4. 帧同步_帧同步和状态同步该怎么选(上)

    这是一篇拖延了2年多的文章-2017年10月份开始写的,直到这次过年才写完... 前言 随着王者荣耀的崛起,使用帧同步(Lockstep)的游戏也越来越多,关于帧同步和状态同步的讨论争论也有不少,那么 ...

  5. 多人网络游戏服务器开发基础学习笔记 I:基本知识 | 游戏设计模式 | 网游服务器层次结构 | 游戏对象序列化 | 游戏 RPC 框架 | 帧同步和状态同步

    今天继续开新坑,尽管过了很多 Unix 套接字编程的坑,但是实际还是有很多不同场景和性能的需求,以及最服务器架构的内容也就接触过 preforking 和 master 带 worker 而已. 所以 ...

  6. Unity帧同步和状态同步

    帧同步 适用游戏类型 对于延迟要求较高的游戏,例如:FPS游戏, RTS游戏(即时战略游戏)等. 原理 帧同步不同步状态,只同步玩家的操作指令,操作指令包含当前的帧索引.这里最重要的概念就是 相同的输 ...

  7. 游戏帧同步和状态同步

    在网络游戏中,服务器和客户端的同步技术是一个绕不开的话题,也是在技术选型时,首先需要确定的方案.网游中的同步技术主要有两个技术方向,帧同步和状态同步.本文简单讨论了帧同步和状态同步,整理并对比了他们的 ...

  8. 帧同步与状态同步:方案比较

    状态同步:大型的MMOARPG ,比如魔兽世界 帧同步:网络条件好的局域网,比如魔兽争霸,优化过的MMRPG, 比如王者荣耀 相比之下状态同步适用型更广,特别适合复杂度高,延迟要求高,玩家多的游戏,例 ...

  9. 网络游戏中的帧同步与状态同步

    帧同步的基础概念 相同的输入 + 相同的时机 = 相同的输出. 客户端发送操作信息到服务器,服务器收到后转播给所有的客户端,客户端接收服务器的操作信息后计算游戏行为的结果, 然后通过广播下发游戏中各种 ...

  10. 帧同步和状态同步笔记

    资料都来自于网络. 前言 网络同步模式的演化史 概念 P2P模型 Packet Server(包的简单中继) 参考 前言 在制作网络游戏的时候,经常会讨论同步方式.同步这个话题就是让不同客户端的游戏表 ...

最新文章

  1. 日志切割清理工具 Log-Cutter
  2. python爬虫学习(三):使用re库爬取淘宝商品,并把结果写进txt文件
  3. 用户控件和自定义控件
  4. 更新版-梳理前端开发使用eslint和prettier来检查和格式化代码问题
  5. 垃圾回收(GC)浅谈
  6. 字符串格式化漏洞修改GOT表一例
  7. 框架--NoHttp和OkHttp哪个好用,Volley和NoHttp哪个好用?
  8. ExtJS4之helloworld
  9. web-http协议-请求协议-响应协议
  10. Hive 内置函数权威指南,操作大全
  11. Java Spring连接Tibco Queue 总结
  12. recycleview 自动循环滚动_划重点 | 不能不知的滚动轴承知识—轴承分类(续)
  13. (转)Struts2的标签库
  14. Android camera开发(9)---Dual Camera(MTK solution)开案说明
  15. 约瑟芬公主把乔治放在了第三位,对吧
  16. 适合于图像处理方向的SCI期刊杂志列表【转】
  17. oracle 已知表名查询所属的schema_sql注入联合查询总结
  18. Devexpress 10.1.6 源代码重新编译成功(DXperience 10.1.6 重新编译)附所有需要用到的资源下载地址 (收藏)...
  19. c语言常量指什么作用,c语言字符常量是什么
  20. Windows查看所有共享

热门文章

  1. 矿大教务系统接口开发记录
  2. 两行代码隐藏进程在top中的显示
  3. 又被黑!百度到底做错了什么?
  4. 百度被“黑”给网吧敲响 网络暗战的警钟
  5. 2021 西湖论剑 pwn blind
  6. 解决工作流:org.activiti.engine.ActivitiException: Unknown property used in expression: ${AAAAA}报错
  7. Tranformer模型与Softmax函数
  8. 【语音识别】基于MFCC和MEL倒频系数实现声纹识别附matlab代码
  9. int 字节在32位 64位系统的区别
  10. 多通道(Multichannel)单通道(singlechannel)图像