技术标签: 帧同步
谈到网络游戏,不可避免要谈到现有两种比较常见的网游同步技术:帧同步和状态同步
说到这两个名词,大家夸夸奇谈,都能讲上些许自己的见解,我反正啥也不懂
这篇文章就打算着重学习一下这两种技术的基础和原理
网络同步的目标就是时刻保证多台机器的游戏表现完全一致。
网络同步 = 实时的多端数据同步+实时的多端表现
同步战斗逻辑是包括技能逻辑、普攻、属性、伤害、移动、AI、检测、碰撞等等的一系列内容,这常常也被视为游戏开发过程中最难的部分。
网络同步按大类来分有两种做法:状态同步和帧同步。需要强调的是这两个概念并不是简单的对立概念,其中的差异包括:"数据格式与内容"、“逻辑的计算位置”和“是否有权威服务器”等。
LockStep的翻译是锁步同步,是齐步行军的意思
服务器对客户端指令进行收集和转发
针对传统严格帧锁定算法中网速慢会卡到网速快的问题,实践中线上动作游戏通常用“定时不等待”的乐观方式再每次Interval时钟发生时固定将操作广播给所有用户,不依赖具体每个玩家是否有操作更新:
状态同步顾名思义就是同步各个客户端的状态,保证每一次操作后的状态是一致的
通过开发服务端程序,把用户的操作作为输入实时上传到服务端,服务端通过计算返回结果给各个客户端,这样的过程就是状态同步。
虚幻引擎的网络同步模型
如今的状态同步:增量同步、RPC(远程过程调用)两种同步手段。
目前状态同步多用于CS架构,客户端通过RPC向服务器发送指令信息,服务器通过属性同步(增量状态同步)向客户端发送各个对象的状态信息。我们可以才有预测回滚、延迟补偿、插值等优化方式
区别表格
属性 | 帧同步(LockStep) | 状态同步 |
---|---|---|
确定性 | 严格确定 | 允许小误差,定时纠正误差数据 |
表现与响应速度 | 传统严格帧锁定要等其他客户端消息全部到达,响应比较慢;乐观帧锁定可以做到本地立刻响应,但是需要回滚的时候,体验就没那么好了 | 一般会做预测,可以做到立刻响应。不做预测的话,响应时间是一个往返时间(RTT) |
带宽与流量 | 带宽随人数增加而增加,不适合MMO | 需要发送各种状态数据,带宽占用比较高。可以通过压缩、裁剪、增量等方式优化。人数较少时候不如帧同步剩流量 |
网络延迟适应性 | 要求较低的延迟。如果延迟较高,所有玩家体验都不好。即使采用乐观帧锁定优化,高延迟下也容易产生卡顿 | 适应性较高,方便做各种插值优化。当然高延迟下,也容易产生位置突变 |
开发难度 | 初期开发减法,框架容易实现,但是后期解决bug和完善系统很困难。比如浮点数、随机数、执行顺序导致计算结果不一致,问题很难排查 | 框架比较复杂,客户端服务端一套代码,每个功能都需要客户端服务端联调。问题定位比较容易。也会出现时序问题 |
玩家数量 | 适合少量的玩家,比如ACT、MOBA | 可多可少 |
跨平台 | 不适合跨平台,会有浮点数问题,可以用定点数来将误差控制在一个可接受范围,同时可以定时纠正结果 | 适合。有权威服务器 |
反外挂 | P2P架构不适合反外挂,如果引入战斗服务器来校验各个客户端结果,可以解决常见外挂,但是透视和全图视野防不了 | 与服务器加入校验机制,可以起到比较好的反外挂效果。但是一样防不了透视外挂 |
中途加入和断线重连 | 比较复杂。可以在断线的时候,通过快捷播放服务器同步的帧数据来快速跟上游戏 | 容易。由于实时记录了各个对象的状态信息,所以重连的时候,直接创建这些对象,并同步信息即可 |
性能(客户端) | 客户端要跑完整逻辑,还要执行渲染逻辑,开销比较大 | 可以灵活优化,客户端跑较少逻辑 |
回放(离线) | 本身收集了所有玩家的输入信息进行逻辑推进,天然支持回放,且回放文件比较小 | 可以支持回放,但是逻辑比较复杂,需要不断记录状态信息,同时回放时候需要读取合适的时间。回放文件大 |
回放(实时) | 比较复杂,客户端需要本地对全场状态进行序列化,才能回到目标时间。播完回放后还需要加速追上实时游戏状态 | 相对容易,可以方便的记录快照信息,并按照录制内容随时播放 |
帧同步和状态同步游戏
老话题,选择 TCP还是 UDP,答案是大部分时候,TCP打开 NODELAY即可,现在网络情况好了很多,没必要引入新的复杂度。即便是“帧锁定算法”上线的多人实时格斗游戏,也有在用 TCP跑着的。
当然,等到你的游戏发布出去了,开始挣钱了,你想改进你的游戏效果,特别是高峰期的卡顿比例(需要收集客户端统计),那么你可以使用 UDP来改进,《街霸4》和《英雄联盟》都是使用 UDP的,比如你可以使用 libenet(英雄联盟用的)。不过 libenet所采用的传输技术,是上世纪的标准 ARQ做法了,《街霸4》所采用的传输技术远远高过 libenet,如果你想采用更为现代的传输技术,赢得更低延迟的话,可以使用“快速传输协议-KCP”,被再若干上线项目和开源项目使用的协议,效果远远 PK libenet。
在使用 KCP时,你可以用在你 TCP的基础上,再登陆时服务端返回 UDP端口和密钥,客户端通过 TCP收到以后,向服务端的 UDP端口每隔一秒重复发送包含握手信息,直到服务端返回成功或者失败。服务端通过 UDP传上来的密钥得知该客户端 sockaddr对应的 TCP连接,这样就建立 TCP连接到 UDP连接的映射关系。为了保持连接和 NAT出口映射,客户端一般需要每 60秒就发送一个 UDP心跳,服务端收到后回复客户端,再在这个 UDP连接的基础上增加调用 KCP的逻辑,实现快速可靠传输,这样一套 TCP/UDP两用的传输系统就建立了。
中国的网络情况比较特殊,会存在有些网络 UDP连接不上的情况,因此都是先连接 TCP,然后试图 UDP,UDP不通的情况下,退回 TCP也能正常游戏,一旦 TCP断开,则认为 UDP也断开了。
不果归根结底,还是先上 TCP,再根据自己游戏的特点和是否出现传输问题,选择 UDP。
下面对状态同步相关的一些优化技术进行学习。
首先问个问题:网络同步优化到底在优化什么?
我们进行网络同步优化,主要是想将网络延迟进行优化。
表现优化主要是想弱化玩家对延迟的感受
5.1.1 插值优化
在状态同步中,由于客户端每次收到的是其他角色的位置信息,为了避免位置突变,客户端会采用插值技术,让表现更平滑,而不是跳帧。
具体应用的时候,可以用使逻辑帧和渲染帧分离
5.1.2 客户端预测+回滚
关于预测,就是本地先执行。
把玩家本地预执行的指令都记录好时间戳并存放到一个Move_Buffer列表里(类似滑动窗口)。在添加了时间戳条件下,收到了一条过时的服务器位置数据。
延迟对抗主要是想弱化玩家对延迟的感受
5.2.1 延迟补偿(Lag Compensation)
延迟补偿就是弥补客户端到服务器同步延迟的一项技术,核心就是 服务器在指定时刻对玩家角色进行位置回滚与计算处理。
实现方式:服务端会定时记录所有玩家位置。假设客户端到服务端的延迟为Xms,当服务端收到客户端操作后,服务端使用记录的Xms前所有玩家位置来计算是否命中,从而抵消延迟带来的问题
延迟补偿缺陷:使用延迟补偿要考虑游戏类型。不适合ACT网游
5.2.2 命令缓冲区
把远端数据缓存在一个buffer里面,然后按照固定频率从buffer里面取,可以解决客户端卡顿已经网络抖动问题。
不过缓冲区和延迟是有冲突的,缓冲区越大,证明我们缓存远端数据越多,延迟越大!
守望先锋的InputBuffer
5.2.3 假表现
真实开发环境下,我们可以根据游戏的具体情况,加一些前摇动画来掩盖延迟。比如在无敌状态前播一个前摇动画等。
丢包对抗主要也是弱化玩家对延迟的感受
5.3.1 使用TCP
TCP不会丢包,对于延迟不敏感的游戏,优先采用TCP
5.3.2 冗余UDP数据包
一次性发送多个帧的数据来对抗丢包。
对于数据量比较小的游戏,可以采用冗余UDP的方案,即后续的UDP包会冗余一定量前面已发送的UDP包。
带宽优化的目的是减小客户端及服务器的同步压力。
5.4.1 同步对象裁剪
剔除不需要同步的对象。比如一个玩家离我很远,远到他的任何行为都不会影响到我,那我们就可以把他剔除,不进行同步给我,我不关心他的任何数据。
常见的裁剪方式有很多:SOI(Spheres Of Influence)、静态区域(把场景划分成多个区域,不在一个区域不同步)、视椎裁剪、八叉树裁剪、AOI(Area Of Interest)
着重讲一下AOI(Area Of Interest):根据玩家位置,维护一个动态的视野列表,视野外的对象会被完全忽略。实现方式有很多,常见的是基于格子的空间划分算法。虚幻引擎的大世界同步框架ReplicationGraph核心思想也是这个
5.4.2 分区、分房间
对于大型MMO来说,这是常见手段。将不同玩家分散到不同场景(不同服务器),这样可以减小服务器压力,降低延迟。但是也带来了跨服数据同步的问题
5.4.3 数据压缩和裁剪
坐标和旋转是我们场景的同步内容,但很多数据是不需要同步的。比如旋转的话,如果只需要一个Y轴旋转,我们可以传个float,而不是vector。比如我们可以压缩浮点数的精度。
然后对于状态同步,可以采用增量发送的方式来减少数据量
5.4.4 减少遍历和更细粒度的优化
对同步对象做优先级划分,发送频率调整等。
5.5.1 提升帧率
不同游戏的性能瓶颈不同,需要具体分析,包括:内存问题(GC、频繁申请与释放)、IO(资源加载、频繁读写文件,网络包发送频率过大,频繁读取数据库)、逻辑问题(大量遍历循环、无意义的Tick、过多的锁、高频率Log)、AI(寻路耗时)、物理问题(复杂模拟、碰撞检测)、语言特性等,客户端还有各种复杂的渲染问题(Draw Call太多,半透明,动态阴影),不断地优化,才能把帧率提高和稳定
5.5.2 保持帧率稳定和匹配
保持服务器帧率稳定
5.5.3 分摊计算压力
对于MMO这种服务器压力比较大的游戏,可以把一些复杂计算转交给客户端进行计算(甚至计算后返还给服务端),比如物理、寻路、AI等。
文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态
文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境
文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn
文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker
文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机
文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk
文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入
文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。 Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。
文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动
文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计
文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;gt;Jni-&amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图
文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法