Unite 2017 | 从《闹闹天宫》看MOBA游戏里的网络同步技术

http://mp.weixin.qq.com/s/0v0EU79Q6rFafrh8ptlmhwhtml

 

在Unite 2017 Shanghai案例分享专场,来自蓝港互动《闹闹天宫》项目组的主程序陈实为你们分享了MOBA游戏里的网络同步技术,总结了使用Unity开发MOBA类型游戏在网络同步上可能遇到的问题,以及如何规避这些问题的宝贵经验。本文就为你们带来这次分享的技术要点。数组

 

 

 

MOBA类游戏的网络同步有三大特色,也能够理解为MOBA游戏对网络同步的三大要求,即实时性、流畅性以及游戏公平性。知足这些网络同步要求经常使用的技术方案有两种:状态同步与帧同步。下面就分别针对这两种经常使用方案及其对应的实际案例,来分析两种方案对于各类网络环境的表现。并着重分享《闹闹天宫》项目选用帧同步方案进行开发的过程当中,所遇到的一些难点与挑战。安全

 

下面附上本次主题分享的现场视频:服务器

 

 

状态同步网络

状态同步,即同步玩家的状态信息,例如位置、属性以及其它玩法相关数据等。一般在此种方案下,游戏主逻辑会放在服务端进行计算,客户端仅用做显示。而通讯须要的网络流量大小,取决于玩法设计中须要同步的实体数量。数据结构

 

状态同步结构图架构

 

对于像《星际争霸》这类RTS游戏来讲,这种同步方案就不太适用,由于玩家能够操做的小兵数量可能上百个,状态同步会占用大量流量。状态同步须要客户端接收玩家输入后,上传到服务端进行数据处理,而后将状态信息传回客户端进行展现。函数

 

帧同步性能

帧同步仅同步玩家指令,不一样步状态,游戏逻辑一般会在客户端分别计算。网络流量大小取决于指令大小以及同步帧率。像《星际争霸》这类游戏即便须要同步的单位增长到两三百,所需的网络流量也不会有明显增长。而帧同步的技术重点及难点在于如何保证全部客户端的计算结果一致。优化

 

帧同步结构图

 

帧同步大体的结构为,客户端将输入发送给服务端,而后服务器以统一的帧率将各个客户端的输入转发给其它客户端,各个客户端收到全部输入后在本地统一进行计算。

 

优缺点比较

 

 

状态同步

联系方式

录像文件大小

一等奖

138XXXX9572

流量消耗

一等奖

138XXXX9572

开发调试难度

一等奖

138XXXX9572

安全性

138XXXX9572

可否离线战斗

额外开发

138XXXX9572

网络卡顿时表现

额外开发

见下文

 

一般采用帧同步的开发和调试难度相比状态同步会高一些,由于状态同步仅需维护好服务端的一份逻辑,而帧同步较难保证全部客户端的一致性。从安全性来讲,状态同步相比帧同步会更加安全,帧同步在客户端进行计算会面临被Hack的问题。对于运行在手机网络环境下相当重要的离线战斗功能,采用帧同步机制无需额外开发,而状态同步则须要单首创建离线战斗的逻辑。

 

帧同步方案下的录像文件更小,由于帧同步仅需保存指令。若是使用状态同步,这个文件相对会很大,在储存与传输上难度都较高。

 

状态同步一般须要消耗更大的网络流量,由于可能须要同步的数据量很大。在网络卡顿的状况下,状态同步方案会出现角色闪现的问题,由于状态同步一般会在本地进行一些预计算,可能会与最终服务端的计算结果不一致,重置客户端计算结果时就会发生闪现的问题,能够额外作一些处理来避免闪现。而帧同步方案在网络环境不理想时,会出现一些动做和输入的延时。

 

案例分析

目前采用状态同步方案的游戏有你们熟知的《Dota 2》、《守望先锋》及《全民超神》。采用帧同步方案的有《Dota》、《风暴英雄》及《王者荣耀》。通用的两种方案都有各自的优缺点与适用状况,建议你们根据实际项目需求选择最合适的方案。而《闹闹天宫》游戏采起了帧同步的方案,下面就结合《闹闹天宫》的开发经验,为你们分享帧同步方案的重难点。

 

 

Dota游戏截图

 

帧同步方案的重难点主要在于三个方面:保证肯定性、流畅性以及针对外挂的处理。保证肯定性即确保全部客户端的计算结果一致,这也是帧同步方案最大的难点。首先,要注意确保客户端的核心逻辑和同步帧率一致。另外,对于须要使用随机数的地方,保证初始化种子同步,且全部客户端的随机数调用次数一致。还需考虑到变量初始化、基准判断数据以及数据结构遍历顺序等可能会致使客户端不一样步的问题。

 

其次是流畅性,影响游戏流畅性的因素有二,网络延迟与画面卡顿。网络延迟会致使玩家输入与反馈之间的延迟,画面卡顿则说明游戏性能存在问题。对于实时性要求较高的MOBA类游戏,推荐使用UDP,而后手动处理丢包与顺序问题。对于画面卡顿,要将显示与逻辑分离,保证即使在底层逻辑上物体是抖动的,在客户端显示上也能看到物体流畅移动。

 

最后讨论针对外挂的处理,外挂一般会修改游戏属性,若是使用帧同步,就须要检测本地数据是否有修改,或者将本地数据进行Hash运算后传到服务端进行校验。若是服务端没有该逻辑,也能够将其它客户端的数据发送到服务端比较两个客户端数据是否不一致,从而判断是否某个客户端出现了异常。帧同步除了同步指令外,也能够选择性地同步一些关键数据,来避免出现客户端数据被修改的问题。

 

结语

关于《闹闹天宫》的网络同步经验就为你们分享到这里,相信其中分享的内容对于非MOBA类的其它游戏也会有帮助。咱们还会继续分享一些Made with Unity游戏及VR/AR内容的开发经验在Unity官方中文社区(unitychina.cn),请保持关注!

 

 

 

 

 

 

 

转自:http://www.gameres.com/750888.html

在5月13日Unite 2017 案例分享专场上,蓝港互动《闹闹天宫》项目组的主程序陈实分享了MOBA游戏的网络同步技术经验,如下为详细内容:

  你们早上好,如今自我介绍一下,我叫陈实,来自蓝港互动,如今是《闹闹天宫》项目组的主程序。我今天的主题是MOBA游戏的网络同步技术。这个主题昨天王者荣耀跟今天《球球大做战》都涉及到一些,我讲的内容可能会更底层一些,更接触咱们实践细节的部分。我不是在这里教会你们怎么作这个网络同步的技术,而是想把咱们在使用这些技术的时候,遇到的坑,还有咱们认为的重点,就是跟你们分享一下,而后可让你们在使用一样的技术方案的时候,能够有一些坑你们就绕过了,若是节约你们开发的时间或者调试的时间,我以为此次分享的价值应该就体现出来了。

  咱们讲这个MOBA游戏里面的网络同步技术,首先须要来了解一下,MOBA游戏这个同步的一个特色。我把它概括为三点,首先要求动如脱兔,就是实时性要求比较高,而后要顺滑如丝,就是流畅性要求比较高。还有一个就是疏而不漏,就是公平性也要有必定要求。可是容许你在一些显示的部分,咱们能够说两边有一些差异,这是能够接受的。可是涉及到核心的游戏玩法的部分必须保证是同样的。

  接下来我会分三个方面跟你们阐述一下这个主题,首先会讲一下咱们在作这个网络同步的时候,经常使用的两种方案,状态同步和帧同步,而后我会结合实际的案例来分析一下,哪些游戏用哪一种方案,你们用对应的方案,能够分析一下对应的作的比较好的游戏,而后还会看一下,就是在网络延迟的状况下两种方案表现有哪些不同。最后会着重介绍一下咱们项目在使用帧同步这个方案的时候,遇到的一些问题,而后里面的一些重点和难点。

  那么讲一下状态同步和帧同步。先说一下状态同步,状态同步顾名思义,就是同步玩家的状态信息,好比位置,他的属性,还有其余跟玩法相关的数据。一般使用这种方案主逻辑基本上都在服务器运行,都在服务器进行计算,客户端只是做为一个显示。还有一个特色,就是咱们通信的网络流量大小是依赖于你的游戏里面,你的玩法里面,须要同步的一个实体数量。

  咱们知道之前玩的比较多一些RTS游戏,像星际争霸,就不太会使用这种状态同步的方案,他们能够操纵兵的个体的数量是很是多,可能有上百个单位,若是这样用状态同步的话,流量就会很是大。咱们看一下这个方案的结构图,你们能够看到,客户端会把一些,把他们的输入发给服务器,而后服务器会作一个处理,把状态信息发到客户端作一个显示。

  咱们再介绍一下帧同步,帧同步不太同样的地方就是,只同步玩家的指令,不一样步状态。一般游戏的逻辑都是在客户端进行各自计算的。这确定带来一个问题,就是说你要在各客户端各自计算,你怎么保证在各客户端算出来的结果是同样,这是帧同步的技术重点也是难点。而后就是网络流量是不依赖于同步实体的个数,只依赖于指令,这么一个大小,还有一个同步的频率。像星际争霸这种游戏,即便须要同步的单位从一百个加到两百个,加到三百个,对同步的网络流量也不会有特别明显的增长。

  咱们再看一下这个帧同步的结构图,你们看到,客户端会把它们的消息跟它们的输出发送给服务器,服务器会以一个统一的频率把各个客户端的输入转发给其余的客户端,而后其余各个客户端收到你们的输入以后,统一地进行运算。

  下面我就比较一下,咱们认为这几个重点的方面,使用这两种解决方案可能有哪些不同。咱们来比较一下开发和调试难度,咱们认为帧同步的难度是比状态同步的开发调试难度会高一些。由于状态同步的话,可能只须要有一份逻辑在服务器运行,只要写好服务器的逻辑,保证正确就好了。帧同步由于各个客户端去运算,很难说去保证一个一致性,很容易就会出现咱们所谓的不一样步的现象,就各个客户端整个游戏的流程就分开了,两个客户端看到彻底不同的游戏状态。

  下面是一个安全性,咱们认为状态同步的安全性会高一些,由于全部逻辑都在服务器,由于帧同步逻辑是在客户端运算,就存在一些hack,后面会降到一些外挂的问题,咱们若是用这个帧同步方案的话,咱们怎么避免它。

  还有一个是离线战斗,咱们知道在手机上的MOBA游戏,手机上的网络,或者使用场景,网络是不稳定的,可能咱们但愿为了体验好一点,好比单排的时候,或者刚进来的时候第一场新手战斗,咱们但愿跟AI在战斗。跟AI打的时候,不须要去跟服务器进行通信,保证刚开始的时候,体验是很是好的。这个离线战斗也是一个很强的需求,若是你使用的是状态同步的这种方案,可能须要额外去开发,由于一般咱们的Server和Client使用的开发语言是不同的,帧同步自己在客户端算,只须要简单转发一下网络的消息,就能够实现说这么一个离线战斗的逻辑。

  而后消耗流量的大小,一般来说状态同步比较高,缘由也说过了,由于可能须要同步不少不少的属性,而后还依赖于须要同步的实体的个数,还有一个就是网络卡顿的时候的一个表现,状态同步一般的表现是闪现,帧同步就是动做和输入会出现一些延时。为何会出现闪现,由于状态同步一般使用的策略,会在本地作一个预算,你的预算很明显极可能跟服务器算出来的最终结果不同,这样他就会把客户端重置到一个正确的状态,就出现一个闪现的状况。这种是原生就带来这个问题,可是额外作一些处理的话,仍是能够尽可能去避免这种问题。

  还有一个就是咱们说的录像文件的大小,录像文件的大小,这也是比较重要的。由于如今手机游戏你们都但愿去分享你的战斗,分享你的精彩的时刻。若是你使用状态同步的话,这个录像文件比较大,帧同步由于只存指令是比较小的,若是录像文件比较大,你的储存、传输都是很大的问题。

  下面我再结合具体案例再讲一下,咱们来看一下,若是想使用状态同步的话,你能够去研究一下《Dota2》,他使用状态同步的一个缘由,由于Dota2的厂商,有一个Source引擎,这个引擎基本上就是为FPS类游戏开发的,而FPS一般都是使用状态同步,由于他们使用这个引擎,选择状态同步这么一种方案,不少代码就能够复用。因此能够看到状态同步也能够在MOBA游戏上获得一个很好的表现。还有就是你们比较熟悉的《守望先锋》,他就是一个典型的FPS游戏。咱们看一下使用帧同步的游戏,帧同步就是《Dota》,他是基于魔兽争霸3,还有就是《风暴英雄》,《风暴英雄》使用星际争霸2的引擎,因此说就沿用了帧同步这么一个结构。

  还有如今最火的《王者荣耀》,若是你们使用对应的方案能够研究一下这些游戏,他们的表现。下面截了一张,你们能够看一下,这是腾讯的全民超神,你们能够看到使用状态同步方案,这个在400毫秒延迟的状况下,你们看一下下面的小兵和英雄,就会出现闪现的状况,还有一个你看最后英雄被击杀的时候,没有人打你,你却莫名其妙的死了,这是一个典型的状态同步在弱网络环境下的表现。再对比看一下《王者荣耀》,王者荣耀一样是400毫秒延迟的状况下,看一下王者荣耀的表现,你明显能够看到左边的摇杆往下以后英雄并无当即跟着往下,而是过了一下子才往下。可是你是怎么死的,或者你的运行轨迹是怎么样的,仍是看的很是清楚的。我以为可能右边这种表现是更好的一种表现。

  上面就粗略地介绍了一下,咱们通用的两种方案,我认为没有最好,只有最合适的,你们根据本身游戏的一些需求和你策划的玩法来选择,使用哪种同步方案。

帧同步的重难点

  我会从三个方面来说,一个是怎么样保证肯定性,而后怎么样说能保证是流畅的。最后再来讨论一下外挂的问题,外挂的处理。  首先讲一下肯定性,要保证肯定性,这是帧同步方案最难的地方。那么你要保证这个肯定性,就是说各个客户端根据一样的输入,算出一样的结果,虽然这句话很简单,可是想要作到算出一样的结果是很是困难的。咱们能够注意哪些问题呢,首先必定要把各客户端的核心逻辑的同步频率保持一致。若是你的频率不同,好比用Unity的函数,每一帧运行时间间隔不同,若是这个不同的话会带来很是多的问题,基本上是不可能算出同样的结果,首先第一步就把这个频率调成同样的。  而后是随机数,咱们不少游戏的话,确定会使用到一些随机的东西,随机数在使用的时候,咱们几乎不能使用Unity自带的随机数,由于咱们知道咱们一般使用的是伪随机数,咱们为了保证在各客户端的随机数是同样的,须要作哪些工做。首先须要把初始化的种子要同步,它们是同样。而后还要保证在各个客户端上,随机数调用的次数是同样。  为何不能使用Unity提供的随机数,由于这个随机数可能会被一些粒子系统,一些别的内部系统去调用,咱们是没有办法控制这些调用的次数的,因此,咱们须要实现一个本身的随机数,来保证他的调用次数。而后浮点数,这也是讨论比较多的主题了,到底咱们是应该使用浮点数仍是定点数来计算这个物理。据我所知,除了一些在主机上发布的,由于他们只在PS4或者xbox上运行他们的游戏,由于PS4和Xbox硬件架构是同样,能够得出结果。可是硬件架构不同,或者用不一样的编译器编译咱们的代码,能不能保证浮点数是同样的结果,应该是能够,可是基本没有看到哪家厂商有这样实现过,为了作到这一点须要作很是多额外的工做,可能须要针对不一样的CPU,而后不一样的编译器来优化咱们的代码,还要作一些额外的工做,才能保证算出来的结果是同样。咱们一般仍是用定点数来算。  下面这点,为何说帧同步开发难度比较高。若是不是很了解这个架构的人去写这个游戏逻辑的话,就极可能很天然使用一些本地的数据,就是一些客户端独有的数据,这我的能不能看到,渲染物体的位置等,可能这个位置在各客户端上都是不同,若是拿这个来作判断的话,就很容易显示出来不一样步,由于条件不同,那么算出来结果天然就不同了。这个可能就得根据大家游戏的一个设计,还有你的编码来去判断了,就你们可能须要注意这个问题。  若是咱们在使用一些第三方库的话,好比使用一些box2D这种库,使用本身开发的库来作物理运算的时候,仍是注意这个问题,可能一些变量没有初始化,那在不一样平台上,或者不一样编译器编译出来的代码,初始的值是不肯定,若是用这个变量去运行一个逻辑的话,极可能就不一样步了,并且还很难意识到这个问题。若是脑子里面有这个概念,变量是必须初始化,就能避免这个问题,同时发生问题的时候,也能够往这个方面想一下。  而后就是一个遍历的顺序也会致使不一样步,咱们的一个经研究说,咱们常常用Dictionary这个结构,你用这个结构是有问题,你可能天真地认为,往Dictionary顺序插入一二三四个元素,他是否是按一二三四的顺序去遍历,官方是不能保证的,若是用这个结构,你们能够尝试使用另一种SortedDictionary这个容器,这个容器有一些开销,若是不频繁插入的话是没有什么问题。  而后就是Raycast返回的结果,在使用Unity的函数,可能会反馈给你一个结果,你碰到哪些东西。这个结果的东西也是不能保证,这个怎么办,咱们解决方法给每一个实体会有一个惟一的ID,这是咱们本身逻辑里面的惟一ID经过这个ID作一个排序,最后排完序之后再使用Raycast的结果。  咱们游戏一些上层游戏逻辑是用Lua来编写的,Lua里面有一个Table,使用这个结构也是注意这个问题,把他当成hash表来遍历的时候,这个顺序也很难保证,咱们必定要使用这个ipairs来遍历,就是当成一个数组来遍历。  下面是流畅性,讲流畅性以前,先了解一下,你不流畅的时候,究竟是一个什么样的表现。一般玩家反馈给你,只会反馈给你,一个是卡,或者说一卡一卡,或者卡卡的。玩家不会告诉你说,我是看到这个东西网络是否是延迟了,或者说怎么样?不会这样,他会给你的是一些很感性的词。当玩家在说卡的时候,他在说什么?其实他在说输入和反馈之间存在延迟。输入和反馈之间存在延迟,这极可能就是咱们的网络,可能存在说你丢包要重发,就是网络延迟。  还有一个是画面卡顿,画面卡顿的话,游戏存在性能问题,刚才咱们《球球大做战》跟咱们分享了优化的对你们也是挺有帮助的。而后还有一个就是游戏物件在来回抖动,可能不是由于你的网络延迟,也不是由于性能问题,可能单纯只是由于你的这个物体,因为你逻辑上有问题,致使它看起来在抖动,咱们就遇到过这个问题。  下面讲一下咱们怎么来保证这个流畅性,TCP仍是UDP,这个问题讨论的很是多了。一般来讲,咱们认为对实时性要求比较高的MOBA游戏,咱们仍是选择UDP,有些游戏也是选择TCP,其实也是作的挺好,也能够根据本身的游戏需求,若是你以为TCP还OK,那就选择TCP没有问题,很成熟,也很可靠。不须要作额外的工做。若是你以为你的游戏对你的实时性要求比较强,仍是推荐你用UDP,使用UDP带来什么问题,首先UDP是不可靠的传输协议,可能须要本身去处理一下丢包,还有顺序。一般经常使用的解决方案就是增长冗余数据,若是一次发包,能够一次带两帧的数据,若是丢包以后,丢了一个包,可是仍然可能仍是有额外的一帧供你使用,继续去渲染。  使用UDP,还有一个问题是说,中国网络国情,有些网络是连不上UDP的,在这种时候仍是须要处理一下,就是在UDP连不上的时候,是否是还要回去使用TCP。若是你们想要进一步了解TCP和UDP,我推荐你们一本书TCP/IP详解,这个里面讲的是很是清楚的。  第二个是Tran位置的更新顺序,这是流畅性提到第三点问题,其实并非由于网络延迟,也不是由于你的性能有问题,而是由于你的,就是更新有问题,而致使玩家看到抖动。而后会经常使用的一个方案就是说,使用这个运动补间,这就没什么好说的。这个还有一个问题,你们还会有疑问,刚才说到了,咱们刚才说的,要全部客户端算出同样的结果,若是用运动补间,由于这个运动补间是基于渲染帧,这个帧率也不能保证是固定间隔去调用的,这个就牵出下面一个问题,就是说你的显示和逻辑必定要分离。你看到的这我的物的真实位置并非逻辑位置,就是客户端已经拿到真实位置,可是并不把真实位置显示到屏幕上,若是把真实位置显示到屏幕上人物就是抖动,这个玩家体验是很差,可是底层逻辑是抖动,可是显示的物体是流畅的在移动的,我以为这个玩家是能够接受的。  下面再来讨论一下外挂,外挂这个问题的话,一般外挂就是修改属性,修改属性的话,若是是使用帧同步的话,修改属性基本上没好说的,虽然是在客户端各自算的,可是因为你的数据并无说去同步,若是只是简单地把本地的数据给改了,好比把攻击力从10调到一万,去秒杀你,但这没什么用,由于别的客户端攻击力尚未提升,别的客户端看到仍是正常,这种时候咱们可能须要一个检测,是否本地有一些修改。可能你会会把一个玩家全部的属性作一个Hash,而后去服务器上作一个校验,若是你服务器没有运行这个逻辑,不知道这个值算的对不对,可能须要把别的客户端也发出来作一个仲裁,若是这我的算出来跟其余几我的算出来不同,那更倾向于认为这个客户端确定是有问题的。  修改属性除了刚才说的方法,能够经过一些加密变量的方案,让外挂找不到真实的值在哪里。一般这个效果不是特别好,若是想改的话也是能改,一般仍是会去使用一个校验。  第二个是透视外挂,之前老玩家玩的Dota比较多的,这个外挂仍是比较多的,由于在Dota里面视野是很是重要的,因为全部数据都在本地,你的控制这个玩家显不显示,可能只是一个变量的问题,改了这个东西,就能够看到这个东西。可是对于一些其余的游戏可能,就相对来讲没有那么重要,仍是说看大家的游戏,这个重不重要。若是重要的话,咱们会怎么办?可能须要,一些关键数据。虽然帧同步只同步指令,可是应对外挂问题上,关键的数据仍是选择去同步。好比你的透视只是一个变量的问题,可能就是一个字节的问题,对你网络的带宽就传输的东西影响是很是小的,可是就能够彻底避免这个问题。  还有自动操做外挂,对咱们这种类DOTA的MOBA游戏影响不大,能模拟一个玩家的操做表现很困难。可是对《守望先锋》,这种操做外挂就影响很是大,比熟练玩家瞄的准多了,这个没有特别好的方法,若是所作的是一种类DOTA的MOBA游戏,就不须要去关注这种外挂,一由于也不太可能搞出这种外挂,若是作FPS这种游戏还须要关注一下,目前业界没有特别好的解决办法,仍是会靠一些发动一些玩家去检测来,用真人来检查,来解决这个问题。  最后还有皮肤美化的外挂,若是很严重可能须要处理一下,去作一些检查。若是不是特别严重,也不须要作一些额外的工做。以上就是个人全部的内容了,但愿对你们有所帮助,谢谢你们。

相关文章
相关标签/搜索