从王者荣耀聊聊游戏的帧同步

​这是王者荣耀技术分析系列第二篇,有兴趣请持续关注个人blog和公众号。编程

一、像《王者荣耀》同样红过安全

二、从《王者荣耀》来聊聊游戏的帧同步服务器

三、游戏服务器的架构演进网络

 

农药自从上线以来,依靠着强大的产品力以及腾讯的运营能力,在游戏市场上表现可谓是风生水起,根据第三方的调研数据显示,《王者荣耀》渗透率达到22.3%,用户规模达到2.01亿人,每日的日活跃用户(DAU)均值为5412.8万人。 如此可观的数据,使人十分钦佩。架构

固然了,做为技术人,更愿意从技术上了解去一些王者荣耀的实现原理和架构方式,从中找到新的知识领域,扩展本身的知识边界,丰富本身的专业技能。借助这个游戏,这一篇咱们来聊一聊王者荣耀的技术实现以及同步方式,更多的从MOBA(多人在线战术竞争游戏)方向来解析推理王者的实现方案,如如有分析的不尽的方向,欢迎一块儿探讨改进。如下是主要讲解的几个重点:dom

  1. 服务器架构
  2. 通讯方式
  3. 同步方案
  4. 技能同步
  5. 断线重连

 

1、服务器架构

不难发现,王者荣耀的服务器采用房间模式,每一个玩家登录之后,而后进入大厅,进行匹配游戏。匹配完成以后,把一块儿对战的玩家放到一个房间内进行对战。socket

房间类玩法和MMORPG有很大的不一样,在于其在线广播单元的不肯定性和广播数量很小,并且须要匹配一台房间服务器让少数人进入一个服务器。tcp

这一类游戏最重要的是其“游戏大厅”的承载量,每一个“游戏房间”受逻辑所限,须要维持和广播的玩家数据是有限的,可是“游戏大厅”须要维持至关高的在线用户数,因此通常来讲,这种游戏仍是须要作“分服”的。而“游戏大厅”里面最有挑战性的任务,就是“自动匹配”玩家进入一个“游戏房间”,这须要对全部在线玩家作搜索和过滤,以及为了更好的体验,会对玩家进行分地区进行匹配,以方便得到更快速的同步。编程语言

通常的方式是玩家先登陆“大厅服务器”,而后选择组队游戏的功能,服务器会通知参与的全部游戏客户端,新开一条链接到房间服务器上,这样全部参与的用户就能在房间服务器里进行游戏交互了。动画

 

2、通讯方式

说到通讯方式,通常会有http和socket 两种方式,但http底层也是采用socket,只是每次通讯完成之后都会断开,这种方式对于须要频繁交互的双方来讲,显得效率过低了,因此通常实时要求高的游戏都是采用socket方式来通讯。

但是sokect通讯,又分为两种:TCP vs UDP,具体是采用那种socket类型,须要具体来看游戏游戏类型。如下是两种类型的优劣:

从上面的对比中,咱们能够会发现,关于socket,咱们想作的事情,tcp都帮咱们作了,咱们只须要创建连接,而后像读写文件同样读写就能够了。而udp须要咱们本身设计一切。看到这一切,你可能第一感受就是采用tcp而非udp,那么真实状况是如此么?基于游戏的业务以及场景不一样,我能够明确的告诉你,王者荣耀是采用udp的,包括腾讯多数长连接手游都是采用udp,这是为什么?

一、tcp保证数据可靠性是有代价的

tcp可以保证数据包的可靠性和有序,这一切都帮你封装好了。TCP发送一个数据包,等待一段时间,直到检测到数据包丢失了,若是没有接收到它的ACK,接下来就从新发送丢失的数据包到目标计算机。重复的数据包将被丢弃在接收端,乱序的数据包将被从新排序。以此来保证数据包的可靠性和有序性。

但为了保证可靠和有序,就要保证TCP不管什么状况,只要数据包出错,就必须等待数据包的重发。这是什么意思呐,就是说,即便最新的数据已经到达,但仍是不能访问这些数据包,新到的数据会被放在一个队列中,须要等待丢失的包从新发过来以后,全部数据没有丢失才能够访问。

如此,若是遇到网络环境太差或者不稳定,好比说国内的移动网络,或者是遭遇到了网络阻塞,出现一个数据包丢失,全部事情都须要停下来等待这个数据包重发。客户端会出现等待接收数据,玩家操做会出现卡顿以及响应不及时的现象。

二、udp的可靠性—DIY手动组装

从上面咱们能够知道udp主要在可靠性上主要是不能保证数据包的顺序,好比第100个收到的数据包并不必定是第100个发出的数据包,同时也没法保证不丢包,期间有一个包丢失,udp本是也不会去校检。若是这两个问题解决了,udp的大部分可靠性问题也就解决了。

具体的方案咱们这一篇就不在细说,大致上是如此来解决:

一、为每一个数据包增长序列号,每发一次包,增长本地序号。

二、每一个数据包增长一段位域,用来容纳多个确认符。确认字符多少个,跟进应用的发包速率来以为,速率越高,确认字符的数量也相应越多。

三、每次收到包,把收到的包上序列号变为确认字符,发送包的时候带上这些确认字符。

四、若是从确认字符里面发现某个数据包有丢失,把它留给应用程序来编写一个包含丢失数据的新的数据包,必要的话,这个包还会用一个新的序列号发送。

五、针对屡次收到同一包的时候能够放弃它

3、同步方案

游戏中常见的同步方案,有状态同步和帧同步,通常大型的MMOARPG都是采用的是状态同步,好比魔兽世界,状态同步采用C/S架构,全部的状态由服务器来控制,安全性比较高,可是流量比较大。帧同步采用的是囚徒模式,全部c端强制采用一个逻辑帧率,从而保证输出一致,其特色是流量小,安全性比较差。

王者荣耀采用的就是帧同步,那么具体帧同步是什么,如何实现的,咱们从两个地方来分解:

一、帧率

什么是帧率,可能没有作过client同窗并非很清楚这个术语,咱们从一个小李子来说解一下。我记得小时候有一种小人书,快速翻看就能够看到漫画上的人物会动起来。以下面这种:

超过1M上传不删了,我也无奈

 

因为人类眼睛的特殊生理结构,若是所看画面之帧率高于每秒约10-12帧的时候,就会认为是连贯的, 此现象称之为视觉暂留。这也就是为何电影胶片是一格一格拍摄出来,而后快速播放的,就像上图快速翻小人书同样。

游戏中的全部动画也是采用这种方式来渲染,只不过帧率是有GPU来控制,你所看到的画面都是有都是有GPU一帧帧渲染的,好比30帧/s,你所看到的画面就比较流畅了。而帧率越高你所看到的越流畅。

二、Lockstep—帧同步

帧同步能够说是经过帧率延伸过来的,你能够把一个游戏当作一个巨大的状态机,全部的参与者都采用同一个逻辑帧率来不断的向前推动。

 

咱们看以下2个图:

 

图中是A、B、C三个玩家的时间轴,这个时间轴不是电脑上的本地时间,而是A、B、C联机时定义的一个时间轴。虚线分隔出来时间片称为turn,能够理解成一帧。箭头表示该玩家将本身的操做指令广播给其余玩家。

咱们把一盘游戏当作一个大型的状态机,由于你们玩的是同一款的游戏,所以F是相同的,初始状态S0也是相同的。在第一个turn结束时,全部玩家都接收到了彻底同样的输入I,注意这里的I不是一个值,而是包含了当前游戏中全部玩家的操做指令集合。t1时刻全部玩家的电脑自行计算结果。因为F、S0和I是固定的,因此每一个玩家电脑上计算出的下一个状态S1必定是相同的。

因此经过上面咱们能够知道:

 

一、咱们把游戏的前进分为一帧帧,这里的帧和游戏的渲染帧率并非一个,只是借鉴了帧的概念,自定义的帧,咱们称为turn。游戏的过程就是每个turn不断向前推动,每个玩家的turn推动速度一致。

 

二、每一帧只有当服务器集齐了全部玩家的操做指令,也就是输入肯定了以后,才能够进行计算,进入下一个turn,不然就要等待最慢的玩家。以后再广播给全部的玩家。如此才能保证帧一致。

 

三、Lockstep的游戏是严格按照turn向前推动的,若是有人延迟比较高,其余玩家必须等待该玩家跟上以后再继续计算,不存在某个玩家领先或落后其余玩家若干个turn的状况。使用Lockstep同步机制的游戏中,每一个玩家的延迟都等于延迟最高的那我的。

 

四、因为你们的turn一致,以及输入固定,因此每一步全部客户端的计算结果都一致的。

咱们来看看具体的执行流程:

 

上图中咱们能够明显看到,这种囚徒模式的帧同步,在第二帧的时候,由于玩家1有延迟,而致使第二帧的同步时间发生延迟,从而致使全部玩家都在等待,出现卡顿现象。

4、乐观锁&断线重连

囚徒模式的帧同步,有一个致命的缺陷就是,若联网的玩家有一个网速慢了,势必会影响其余玩家的体验,由于服务器要等待全部输入达到以后再同步到全部的c端。另外若是中途有人掉线了,游戏就会没法继续或者掉线玩家没法重连,由于在严格的帧同步的状况下,中途加入游戏是从技术上来说是很是困难的。由于你从新进来以后,你的初始状态和你们不一致,并且你的状态信息都是丢失状态的,好比,你的等级,随机种子,角色的属性信息等。 好比玩过早期的冰封王座都知道,一旦掉线基本这局就废了,须要重开,至于为什么没有卡顿的现象,由于那时都是解决方案都是采用局域网的方式,因此基本是没有延迟问题的。

后期为了解决这个问题,现在包括王者荣耀,服务器会保存玩家当场游戏的游戏指令以及状态信息,在玩家断线重连的时候,可以恢复到断线前的状态。不过这个仍是没法解决帧同步的问题,由于严格的帧同步,是要等到全部玩家都输入以后,再去通知广播client更新,若是A服务器一直没有输入同步过来,你们是要等着的,那么如何解决这个问题?

采用“定时不等待”的乐观方式在每次Interval时钟发生时固定将操做广播给全部用户,不依赖具体每一个玩家是否有操做更新。如此帧率的时钟在由服务器控制,当客户端有操做的时候及时的发送服务器,而后服务端每秒钟20-50次向全部客户端发送更新消息。以下图:

上图中,咱们看到服务器不会再等到搜集完全部用户输入再进行下一帧,而是按照固定频率来同步玩家的输入信息到每个c端,若是有玩家网络延迟,服务器的帧步进是不会等待的,好比上图中,在第二帧的时候,玩家A的网速慢,那么他这个时候,会被网速快的玩家给秒了(其余游戏也差很少)。可是网速慢的玩家不会卡到快的玩家,只会感受本身操做延迟而已。

5、技能同步

游戏中有不少是和几率相关的,好比说技能的伤害有必定几率的暴击伤害或者折光被击等。按照帧同步的话,基于相同的输入,每一个玩家的client都是独立计算伤害的,那么如何保证全部电脑的暴击伤害一致那。这个时候就须要用到伪随机了。

大部分编程语言内置库里的随机数都是利用线性同余发生器产生的,若是不指定随机种子(Random Seed),默认以当前系统时间戳做为随机种子。一旦指定了随机种子,那么产生的随机数序列就是肯定的。就是说两台电脑采用相同的随机种子,第N次随机的结果是一致的。

因此在游戏开始前,服务器为每一个玩家分配一个随机种子,而后同步给client,如此每一个client在计算每一个角色的技能时候,就能保证伤害是一致的。这也是多数帧同步游戏采用的方案,包括王者荣耀。

----------------------------------------end-------------------------------------

关注我的成长和游戏研发,致力推进国内游戏社区的成长与进步。

想了解更多有料的游戏技术,请关注个人公众号,原创以及独到。

相关文章
相关标签/搜索