浅谈实时对战网络游戏的同步机制

  • 重要的性能指标
  • 三种不同方向的技术实现介绍
    • 非帧状态同步
    • 帧指令同步
    • 帧状态同步
  • 三种同步方式的对比
  • 帧状态同步和ECS架构

实时对战游戏,相信大家都不陌生,一些经典的游戏:《王者荣耀》(MOBA游戏)、《守望先锋》(FPS对战游戏)、《球球大作战》(休闲竞技游戏)、《魔兽世界》(MMORPG游戏),玩家在游戏场景中都能够和其他玩家进行实时同步,现在我们就来讨论一下这些游戏背后的实时同步技术。

重要的性能指标

一般来说,游戏的实时同步技术,有以下一些重要性能指标:

  • 实时性
    所谓游戏的实时同步,是指玩家在游戏内的操作能够立即得到反馈,并且同步给其他玩家,让其他玩家也能尽快的知道该玩家的操作,所以操作反馈的实时性是衡量同步的实现是否优秀的一个关键指标。 玩家的操作反馈越实时,其同步实现就越好。
    不同类型的游戏对操作实时性的要求并不一样,FPS对战类型的游戏,例如《守望先锋》,对操作实时性的要求是最高的,操作反馈延时一般不能超过50毫秒,MOBA类游戏《王者荣耀》,休闲竞技类游戏《球球大作战》,ARPG类型的游戏对实时性的要求也比较高,延迟一般不能超过100毫秒,MMORPG类型的游戏《魔兽世界》对实时性的要求相对低一些,200毫秒以下都能接受。
  • 一致性
    游戏的一致性是指参与游戏的所有玩家看到游戏状态都是一样的。游戏的一致性分为过程一致性和结果一致性。过程一致性是指在游戏过程中,所有参与玩家每一帧的状态都一致;而结果一致性是指在游戏过程中,中间的状态可能不一致,但是游戏结束的时候最终的结果必须一致。所有的实时游戏,都要求结果一致性,但是过程不一定要完全一致。很多的实时同步算法,都会以牺牲一定的过程一致来获取更好的效率。
  • 在弱网环境下的流畅性
    现在很多实时游戏,例如《王者荣耀》都运行在移动终端,例如手机上。手机上的移动网络是一种典型的弱网环境,其质量不稳定,延迟高,还经常有丢包,因此能否在弱网环境下流畅的同步是衡量同步实现是否优秀的一个重要指标。
  • 同步玩家数量
    同一场景内可以支持的玩家数量,也是一个重要的指标,不同类型的游戏一般要求差别比较大。对战类型的游戏,例如《守望先锋》、《王者荣耀》,一般场景内的玩家人数都不超过10人;吃鸡类型的游戏,一般场景内的人数不超过100人;MMORPG游戏,例如《魔兽世界》,同一场景内的人数可以达到上千人。
  • 反作弊性
    大部分玩家都期望游戏是公平的,玩家无法通过作弊来获取不当收益,从而影响游戏的公平性,所以反作弊性是一个重要的指标。游戏作弊一般有两种方式,一种是能够查看一些本来应该对玩家保密的游戏信息,例如战争迷雾,这种作弊方式相对没有这么严重。另外一种是可以直接篡改游戏数据,这种方式就比较严重了,会完全破坏游戏的平衡性,要严格避免。一般来说,游戏的客户端比较容易被第三方软件篡改,所以能否通过直接查看或者修改优秀客户端数据就能进行作弊,是衡量同步实现在反作弊性方面表现是否优秀的一个很重要的评价标准。
  • 网络流量消耗
    网络流量永远都是稀缺的,能否尽可能的降低流量消耗是步是衡量同步实现是否优秀的一个重要指标。

三种不同方向的技术实现介绍

所有的设计都是一种权衡,一种实时同步的技术实现要使得所有上述性能指标都表现优秀是不可能的。因此,不同的技术实现会进行一些权衡,牺牲一部分不重要指标的性能来获取另外一部分重要指标的性能更加优异。
下面我们介绍三种不同方向的技术实现:非帧状态同步、帧指令同步以及帧状态同步。这三种实现各有其优缺点,下面我们分别介绍一下这三种同步机制。

非帧状态同步

顾名思义,非帧状态同步的同步不依赖游戏帧,主要是对客户端和服务端之间游戏对象状态的同步,其原理如下:

  1. 服务端启动,创建所有的游戏对象(npc、怪物、机关等),并且保存所有游戏对象的状态集合。
  2. 玩家角色进入场景,服务器创建该角色的游戏对象,然后同步给该玩家客户端所需要的所有游戏对象状态,同时将新创建的该玩家角色的游戏对象状态也同步给其他关注的客户端。
  3. 玩家进行操作,客户端发送操作指令给服务端,服务端对该指令进行计算,根据计算结果修改影响的所有游戏对象的状态,然后将新的状态同步给所有关注该对象的客户端。
  4. 重复以上2和3两个步骤,这样所有的客户端都能够实时的获取到其关注的最新游戏对象状态,完成状态的同步。

非帧状态同步如下图:

通过以上介绍,我们可以知道非帧状态同步有以下特点:

  • 整个同步算法完全不依赖游戏帧。
  • 服务端保存了完整的游戏对象状态集合,而客户端只保存了其关注的游戏对象集,该对象集只是完整游戏对象状态集的一个子集,而且每个客户端关注的子集可能都不一样,因此只有服务端知道完整的场景状态,而每个客户端只知道服务端允许它知道的状态,这样对一些场景内有战争迷雾之类的游戏,无法通过修改客户端来获取场景内所有对象的状态,从而进行作弊。
  • 客户端一般只关注玩家角色视野内的游戏对象,对于地图场景比较大的MMORPG类型的游戏来说,玩家一般都分散在地图场景的不同区域,角色视野内的游戏对象数量远远小于整个地图的游戏对象,因此单个地图场景可以支持的玩家数量较多,最多可以达到数千。
  • 客户端保存的游戏对象状态集合只是服务端的一个副本,对该副本的任何直接修改都会被服务器的最新状态所覆盖,所以想要直接修改客户端游戏对象状态来进行作弊是行不通的。
  • 所有的逻辑计算都是在服务端,客户端不需要运行逻辑计算代码,如果逻辑计算代码有bug,不需要更新客户端代码,降低了维护成本;对客户端的cpu性能要求也有所降低,但是相应对服务端cpu性能的要求提高了不少。
  • 因为非帧状态同步不依赖游戏帧,服务端和客户端的代码可以不一致,服务端场景逻辑架构的选择可以多一些,既可以用反应式(reactor)架构,也可以将逻辑拆分成帧,用心跳式(heartbeat)架构。
  • 所有逻辑状态的计算都是在服务端,客户端无法做逻辑预测,必须通过服务端进行状态同步,在网络延迟比较高的情况下会有比较明显的卡顿;同时相对于指令来说,状态的数据要大很多,因此状态同步占用的网络带宽一般会比较高。

综合上述,非帧状态同步具有以下优缺点:

优点

  • 无法通过修改客户端数据进行开图、串改数据等作弊,具有较好的反作弊性;
  • 能够支持数量较多的玩家,一般单场景能够支持4位数以上的玩家,适合MMORPG类型游戏;
  • 具有强一致性,各个客户端之间不会出现结果不一致的情况;
  • 客户端和服务器代码不需要一致,服务端架构可以自由选择,具有较好的可维护性 ;

缺点

  • 对网络要求较高,需要较高的带宽,一般使用TCP协议,网络质量不好的情况下延迟较高;
  • 所有逻辑计算都放在服务端,对服务端的性能要求较高;
  • 客户端没有逻辑运算,无法做逻辑预测,网络延迟高的情况下会感觉比较卡顿;

适合游戏类型

MMORPG类型的游戏需要支持的单场景的玩家数量较多,对反作弊的要求高,对网络延迟的要求不是特别高,适合使用非帧状态同步。

帧指令同步

帧指令同步,服务器一般不保存游戏对象的状态,只是做客户端帧指令的中转,其原理如下:

  1. 服务端启动,以某个固定的时间间隔运行心跳(heartbeat),每次心跳被称为服务端帧,所有的服务端逻辑都是在服务端帧执行;
  2. 客户端也某个固定的时间间隔运行心跳(heartbeat),每次心跳被称为客户端帧,所有的客户端业务逻辑都是在客户端帧执行(注意该客户端帧是逻辑帧,跟实际的图形渲染帧是分离的);
  3. 每秒能够运行的帧被称为帧率,客户端的帧率一般为服务器的整数倍,例如服务端的逻辑的帧率为15,客户端的帧率可以是服务端的一倍15,两倍30,或者三倍45,4倍60;
  4. 所有客户端就绪后,游戏开始,客户端和服务端帧序列都从1开始,每次心跳递加1;
  5. 客户端在每一帧(客户端帧)都会获取玩家输入,然后转换成帧指令发送给服务端,同时也从服务端获取所有玩家该帧的帧指令,然后根据这些指令进行逻辑运算;
  6. 服务端在每一帧(服务端帧)接收客户端的帧指令,然后在帧结束时,将该帧接收到的所有客户端的帧指令打包后发送给所有的客户端。
  7. 重复4和5步骤,直到游戏结束。

帧指令同步如下图所示:

通过以上原理介绍,我们可以了解,帧指令同步有以下特点:

  • 服务端不做任何的逻辑运算,也不保存任何的游戏状态,只是单纯的做客户端帧指令的中转,因此服务端没有办法对各个客户端的状态做一致性裁决,客户端的状态一致性是通过完全相同的输入,完全相同的逻辑运算,导致完全相同的输出来保证的。所有的逻辑运算都不能有真随机数,对浮点数的运算也要小心,精度要保证一致,同时也不能有任何其他的外部依赖。任何逻辑运算导致的不一致都是不可逆的,会导致最后游戏结果的不同。
  • 所有的逻辑计算都是在客户端,服务端不需要运行逻辑计算代码,对服务端cpu性能和内存容量要求较低,甚至因为服务端没有具体游戏逻辑运算,帧同步的服务端可以做成通用的服务,多个不同的帧指令同步游戏都可以共享。
  • 每个客户端都有完整的游戏对象状态集合,如果破解了客户端,能够查看所有的游戏对象的状态,同时任何对客户端游戏对象状态的篡改,都会导致该客户端的状态和其他客户端的状态不一致,并且这种不一致基本是不可逆的。
  • 服务端不保存任何状态,某个客户端需要中途进入游戏,或者断线后重连,都需要从第一帧的状态开始重新计算到当前帧,这个过程叫做追帧,如果游戏进行的时间较长,这个过程需要较长的时间;

综合上述,帧指令同步具有以下优缺点:

优点

  • 游戏逻辑都在客户端,服务端代码可以通用,代码容易维护,同时占用服务端资源少;
  • 对网络带宽要求较低,可以使用UDP协议,网络延迟较低,适合对延迟要求较高的竞技游戏;

缺点

  • 能够支持的玩家数量较少,一般是在10人以下;
  • 通过修改客户端数据可以进行开图、串改数据等作弊,反作弊性较差;
  • 逻辑计算都在客户端,容易出现结果不一致的情况;
  • 中途进入游戏需要追帧,耗时较长;
  • 只有客户端有逻辑计算和状态保存,服务端不保存状态,因此无法在客户端做逻辑预测和回滚,在网络延迟高的情况下会比较卡顿;

适合游戏类型

MOBA和休闲竞技类型的游戏需要支持的单场景的玩家数量一般都不超过10个,对网络延迟的要求较高,比较适合使用帧指令步。

帧状态同步

通过上面的介绍,我们可以了解,非帧状态同步和帧指令同步都有较大的缺陷,最近比较流行的是将帧指令和非帧状态同步结合起来,实现帧状态同步,其原理如下:

  1. 服务端启动,创建所有的游戏对象(npc、怪物、机关等),并且保存所有游戏对象的状态集合。
  2. 玩家角色进入场景,服务器创建该客户端角色的游戏对象,然后同步当前所有游戏对象的状态给该玩家客户端,客户端保存服务端所有对象状态的副本;
  3. 玩家进行操作,客户端根据当前服务端状态的副本,可以先对该操作指令在本地进行预测运算,同时也将该指令也发送到服务端;
  4. 服务端处理该帧收到的所有玩家客户端指令,根据这些指令进行逻辑运算,运算完毕后更新最新对象的状态,然后将最新的对象状态同步给所有客户端;
  5. 客户端收到服务器最新的状态后,保存该状态,并且跟客户端预测的状态进行比对,如果客户端预测的状态跟服务器的最新状态一致的话,客户端可以开开心心继续跑下去;如果不一致,客户端回滚预测状态到服务端最新的状态,然后从这个状态开始重新进行预测运算,直到最新帧为止。
    帧状态同步如下图所示:

    通过以上原理介绍,我们可以了解,帧状态同步有以下特点:
  • 同步算法必须依赖游戏帧。
  • 服务端和客户端都保存了完整的游戏对象状态集合,客户端可以在玩家发出操作指令后,在本地进行预测计算,而不需要等待服务器计算结果返回再做相关显示,这样可以实现操作在本地实时响应;
  • 客户端保存了所有的游戏对象状态集合副本,可以通过客户端的破解来知道所有游戏信息,从而进行战争迷雾的作弊;同时对该副本的任何直接修改都会被服务器的最新状态所覆盖,所以想要直接修改客户端游戏对象状态来进行作弊是行不通的。
  • 客户端和服务端都有完整的逻辑运算代码,如果逻辑计算代码有bug,需要更新客户端代码,维护成本较高;客户端需要做逻辑的预测计算,如果有不一致的话需要回滚重新计算,对客户端的cpu性能要求也较高;
  • 服务端和客户端的代码必须一致,必须将逻辑拆分成帧,用心跳式(heartbeat)架构。

综合上述,帧状态同步具有以下优缺点:

优点

  • 能够实现客户端的逻辑预测,操作的响应及时,在网络质量不好的时候也能够保证游戏的流畅;
  • 无法通过修改客户端串改数据作弊,具有较好的反作弊性;
  • 支持的玩家数量比帧指令同步多,比状态同步少,一般在100人以内,适合大部分游戏;
  • 具有过程一致性,各个客户端不会出现结果不一致的情况;
  • 使用UDP协议,延迟低,适合需要低延迟的竞技游戏;

缺点

  • 客户端和服务器端代码需要完全一致,代码维护成本较高;
  • 状态保存和逻辑计算在客户端和服务器都有,对客户端和服务端的性能要求都较高;

适合游戏类型

  • MOBA和休闲竞技类型的游戏单场景的玩家数量一般都不超过10个,需要低网络延迟,比较适合使用帧状态同步;
  • 吃鸡类游戏和单地图不超过100人的MMORPG也适合使用帧状态同步;

三种同步方式的对比


对比三种同步方式,我们可以看出:

  • 非帧状态同步在支持人数、同步性和反作弊性有明显优势,但是在实时性上有比较明显的缺陷,比较适合MMORPG;
  • 帧指令同步在各种性能要求上有明显优势,但是在支持人数、实时性、一致性和反作弊性都有明显缺陷;
  • 帧状态同步在实时性和一致性上有明显优势,但是不管是对客户端还是服务端性能要求都比较高,代码较复杂,维护困难一些,适合除了大型MMORPG以外的其他需要实时同步的游戏;

帧状态同步和ECS架构

鉴于非帧状态同步和帧指令同步都已经有很多人介绍,而帧状态同步是属于比较新的技术,一般都使用ECS架构,我后续博客会重点介绍帧状态同步和ECS架构。

浅谈实时对战网络游戏的同步机制相关推荐

  1. 多线程之旅之四——浅谈内存模型和用户态同步机制

     用户态下有两种同步结构的 volatile construct: 在简单数据类型上原子性的读或者写操作   interlocked construct:在简单数据类型上原子性的读和写操作 (在这里还 ...

  2. 浅谈实时数据库系统原理及其应用

    浅谈实时数据库系统原理及其应用 孙俊彦   苏州大学计算机科学与技术学院 摘要: 现代的工程和时间关键型应用对数据库的实时性和对数据直接分析和处理的能力要求特别高,单纯的传统关系数据库已经不能满足需要 ...

  3. 浅谈专有云MQ存储空间的清理机制

    简介:浅谈专有云MQ存储空间的清理机制 在近⼀年的项⽬保障过程中,对专有云MQ产品的存储⽔位清理模式⼀直存疑,总想一探究竟但又苦于工作繁忙.精力有限,直到最近⼀次项⽬保障过程中再次出现了类似的问题,⼤ ...

  4. 浅谈V8引擎中的垃圾回收机制

    浅谈V8引擎中的垃圾回收机制 这篇文章的所有内容均来自 朴灵的<深入浅出Node.js>及A tour of V8:Garbage Collection,后者还有中文翻译版V8 之旅: 垃 ...

  5. java 多线程同步_浅谈Java多线程(状态、同步等)

    Java多线程是Java程序员必须掌握的基本的知识点,这块知识点比较复杂,知识点也比较多,今天我们一一来聊下Java多线程,系统的整理下这部分内容. 一.Java中线程创建的三种方式: 1.通过继承T ...

  6. 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路

    原文地址: http://blog.csdn.net/luoshengyang/article/details/6627260 在前面一篇文章浅谈Service Manager成为Android进程间 ...

  7. 浅谈当前电信检测宽带共享的机制

    本人在深圳,家里用的是中国电信的宽带,之前一直带的是两台电脑,后来把笔记本带回家后就出现了各种无法打开网页的问题.究竟是怎么回事? 时间得推回毕业后的那段时间,某一晚,两台台式机还在正常使用的时候.再 ...

  8. 浅谈Chatbot的架构模型和响应机制

    不知您是否已注意到:人工智能已经不再是少数科技公司的初级原型产品了.在许多服务类行业中,带有人工智能的聊天机器人(Chatbot)正在逐步取代人工客服,提供及时.周到.互动的服务.通过机器学习的相关技 ...

  9. 浅谈JVM的实现与垃圾回收机制

    Java被称为是一个人类可读的编程语言,其主要特点是基于类和面向对象,Java的开源版本被称为OpenJDK.Java编程环境由两个部分组成:Java语言和运行环境,运行环境也称为Java虚拟机(JV ...

最新文章

  1. 【Tiny4412】烧写Qt文件系统到SD卡
  2. input readonly 光标显示问题
  3. 使用OpenCV-python实现颜色特征跟踪视频中的物体
  4. 一位年轻有为的企业家李先生
  5. 内网渗透扫描神器 Perun
  6. Prometheus Alertmanager报警组件
  7. svn利用钩子脚本功能实现代码同步到web目录
  8. springboot图书管理怎么实现借书时间到期提醒_东和店镇第一小学图书数字化管理先进做法...
  9. macbook pro python开发_年轻人第一台 Mac,来自一个开发者的 Macbook Pro 2019 16寸简评...
  10. Android--关闭某个指定activity,android开发游戏
  11. IDC 机房空调问题解决方案
  12. python请输入一个三位数输出该三位数的逆序数_键盘输入一个三位数,输出逆序后的数...
  13. oracle 两表关联查询
  14. div水平(横向)/垂直排列
  15. 抓取每天必应bing背景图片
  16. 数据库 基础 与命令 逻辑思维导图
  17. 东莞女德班被责令停办 学员被遣散并退回学费
  18. python程序设计入门书籍推荐_python刚刚入门,接下来这几本python的书会让你成为别人眼里的大神!...
  19. linux设置网卡开机自启,centos系统怎么设置网卡开机自启
  20. Deep Learning for Modulation Classification: Signal Features in Performance Analysis解读

热门文章

  1. html做出来发给别人链接,FINEBI仪表板的公共链接分享后,将分享的链接发给别人后无法在另外一台电脑上打开该链接网址。...
  2. 英特尔发布酷睿系列 | 历史上的今天
  3. Android 的媒体路由功能应用与框架解析
  4. c语言产生50以内随机数,C语言产生随机数
  5. 为什么U盘中的文件夹和文件全部变成了快捷方式?
  6. 金融民工python学习笔记
  7. The Willpower Instinct
  8. kdb+q一个入库和删除的小demo
  9. c#使用pop3服务器进行邮箱验证
  10. 简单做一段自己CSGO游戏的视频