聊聊网络游戏同步那点事

0x00 前言

16年年末的时候我从当时的公司离职,来到了目前任职的一家更专一于游戏开发的公司。接手的是一个platform游戏项目,基本状况是以前的团队完成了第一个版本,即单人模式的基础玩法,可是以后对该项目的定位又变成了一个本地局域网的联机手游(2-4个玩家)。所以,重写项目底层外加肯定网络同步方案就成了第一件须要去认真考虑的事情了。那么本文就来聊聊网络同步这件事吧。html

0x01 游戏同步中的主次

开发网络多人游戏是一件十分有趣的事情,可是和单机游戏相比无疑增长了更多的挑战。算法

例如,咱们以前开发的单机版本并不须要多么担忧做弊的问题。这是由于购买咱们游戏的玩家(假如咱们的单机游戏难免费发布的话)即使做弊,影响的也仅仅是他本身的游戏体验,不会影响到别人。

可是开发多人游戏就不是这样了,为了保证让每一个人都有好的游戏体验,防止做弊老是须要去考虑的。编程

除此以外,在开发多人游戏时咱们还须要考虑如何“欺骗”玩家的眼睛,让他们认为他们在同一个世界中。服务器

当2个或4个玩家一块儿在手机上玩游戏时,看上去他们确实像是在共享同一个虚拟世界,在同一个世界中游玩。但事实倒是,玩家本身的手机只是对“同一个”虚拟世界的近似模拟。换言之,他们的游戏世界每个都是独一无二的,只不过从外观上看起来像。网络

所以,为了达到这种看上去近似的效果,咱们须要确认哪些状态是须要同步的,只要同步了这些状态,这个游戏世界就看上去同样了。而哪些状态是无需同步的,即这些对象的状态是否同步对整个游戏是否看上去同样并无特别大的影响。运维

在咱们的游戏中,玩家的各类属性、在世界中的坐标、游戏世界中的敌人各类属性、道具获取以及各类触发器的触发等等都有可能会对游戏的表现产生影响,所以须要考虑同步;可是像例如海底的水泡粒子效果、道具获取后的碎裂效果,甚至是背景音乐则不会对游戏的表现产生特别的影响,所以并无必要去同步这些内容。
性能

0x02 同步输入or同步状态

既然明确了不存在两个彻底同样的游戏世界,每一个游戏世界无非都是近似的模拟。那么接下来咱们就要来选择一个适合的网络同步方案以知足这种需求了。最基本的游戏网络同步模型大概能够分为如下4种(画图水平通常,见谅):3d

client-server:专用服务器
client-server:专用服务器
client-server:玩家之一做为服务器
client-server:玩家之一做为服务器orm

peer.PNG
peer-to-peer
peer.PNG
peer-to-peer:帧同步server

client-server

上面的两种client-server模型的相同点都在于有一台机器负责整个游戏世界的模拟,而这台负责整个游戏世界模拟的机器是谁则是这二者最大的区别。在咱们的项目中,咱们借助其中一个玩家的手机做为服务器,咱们叫它Master主机,而通常的玩家设备则被称为Client。固然,更常见的一种情景是游戏开发商或发行商管理的计算机做为服务器,这也每每须要更多的计算机和运维人员。

一般,基于这种同步模型的游戏中客户端不能作出真正的决定。一个情景就是当客户端的玩家按下一个按键,客户端并不会真正的执行影响游戏状态的操做,相反操做会被发往服务器,并在服务器执行它,以后服务器将执行完这个操做以后的结果(一般是游戏世界的状态变化)返回给客户端。

因为你们都知道的网络延迟,所以服务器和客户端并不是时刻保持一致的,为了使游戏玩家的状态变化天然(主要是指玩家的位置、角度等状态),咱们使用的是一种基于插值的同步算法(固然,这种方式也经常被称为影子跟随算法):

  • 服务器间隔固定的时间向客户端同步状态数据
  • 客户端收到数据以后进行同步,通常的属性数据例如血量等等直接根据服务器的值来同步。而诸如位置等信息在客户端则保存为ServerPosition或者称为影子,而客户端的位置则不断向ServerPosition靠拢。
  • 位置同步的过程为了更加平滑,要使用插值,步进距为玩家的移动速度。所以,虽然ServerPosition是跳变的,可是在客户端的表现上倒是连续平滑的。以下图所示,左侧的画面为Server的状态,右侧的画面为客户端的状态,玩家和场景内的怪物位置经过Server告诉客户端,客户端因而开始追赶Server发来的状态。

QQ截图20170222192912.png
固然,将全部的逻辑放到服务器并通过服务器的模拟以后再将结果返回给客户端的过程会带来一些滞后感,当玩家对操做的敏感度要求较高时,这显然不是一个很好的解决方案。所以,客户端的输入预测和服务端的延迟补偿开始获得应用。经过在客户端侧的输入预测,可让玩家的输入获得马上的反馈。而延时补偿则保证告终果的正确性。这个过程能够基本归纳为如下几个阶段:

  • 当玩家按下按钮时,客户端马上执行相应的操做例如开始播放某个动做或是开始移动。与此同时,客户端还会向服务器发送一条包含了时间戳的消息。
  • 服务器通过一段延迟后收到了客户端发来的按钮被按下的消息,因而服务器会回滚到按钮被按下的时刻,在这个时刻执行按钮对应操做,以后再从新模拟到当前时刻。
  • 以后服务器将当前的状态同步给客户端。
  • 客户端收到服务器同步过来的数据,此时因为网络延迟的缘故,客户端收到服务器的消息时也已通过去一段时间。因此客户端一样须要回滚到服务器发出消息的时刻,并根据服务器发送的状态来修正本身的状态。

虽然这样作可以更好的保证玩家的手感,可是咱们发现不管是客户端仍是服务器,一旦收到消息包以后都须要回滚。而这种回滚机制相对来讲较为复杂,而且也不容易在已有的游戏中加入这种机制。

综上,咱们能够看到在这两种同步模型中,服务器获取客户端的操做指令并在服务器内模拟整个游戏世界,以后服务器是将服务器所维护的游戏世界内的状态同步给各个客户端,所以这里主要是作状态同步。

Peer to Peer

Peer to Peer点对点同步模型是一种很经典的网络游戏网络同步模型。带有帧同步模型的Peer to Peer在不少RTS游戏中获得了大量应用,不过在讨论帧同步模型以前,咱们先来聊聊通常的Peer to Peer。

相对于C/S模型拥有一个计算机负责整个游戏世界的模拟,Peer to Peer模式并无单一的计算机来负责模拟游戏世界。相反它将对游戏世界的模拟分配给了全部玩家,于是每一个玩家的客户端都在模拟着本身的游戏世界。这样作的一大好处在于玩家的输入老是马上响应的,我按下一个按钮,按钮形成的结果便发生了,同时我须要作的是将个人操做发送给和我相连的客户端,让他们也去根据我发送的操做模拟游戏世界。可是这样作的一大弊端在于不能保证客户端看到的游戏画面是同样的。
20161223154825585cd6c92ff97.jpg
例如上图上方的怪物射出的子弹能够经过画线来阻挡,可是因为client1和client2都是在模拟本身的游戏世界,所以延迟或是不一样移动设备自己的性能问题就有可能会形成client1的画线操做同步到client2上时产生不一样的结果。因此咱们发现只是简单的让每一个客户端模拟本身游戏世界(就像单机那样),同时简单的将操做同步给别的客户端,至少在同步这个问题上是不靠谱的。

所以,游戏行业大多会采用帧同步模型来保证同步的可靠性。不少早期的RTS游戏都采用了帧同步来做为网络同步的方案。至于为何不少人在介绍帧同步的时候,都喜欢把早期的RTS游戏搬出来做为一个例子呢?我想各位看一眼RTS游戏的游戏截图就能猜到个大概了。
castle war custom hero.jpg
RTS游戏中经常伴随着数十上百甚至上千个逻辑实体单位,若是采用状态同步的话数据量相对要大不少。可是若是只同步玩家的操做呢?若是每一个客户端在相同的状况下开始游戏,而且运行彻底相同的步骤,那么客户端就能够不经过接收状态同步信息就能保证游戏的同步了。

这也是这种模型的一大优点,咱们除了发送玩家的操做以外几乎不须要再发送任何数据。这种同步输入的方式能够说很是适合RTS游戏,由于它们有那么多的单位,同步全部单位的状态是不容易的。
所以,采用这种模型就能够把游戏的过程分为一个一个的回合。游戏的每一步都须要经过网络来收集全部玩家的操做输入,而后再往下执行。固然,一提到“回合”这个词,你们想到每每是所谓的回合制游戏,但事实上只要回合的频率足够快,仍然是能够作出即时游戏的感受。

固然,因为没有同步游戏的状态,而是同步玩家在游戏内的输入操做,所以实现彻底同步仍是有一些事情须要注意的。由于一旦一个小小的不一样步发生,就会产生蝴蝶效应,从而引发很明显的不一样步。一个典型的例子即是我之前在开发一个战斗回放系统时,发现因为一个士兵在寻路的时候稍微走到有点不同的地方,就致使了一场战斗的结果大不相同。

虽然咱们目前的项目并无采用帧同步的方案,可是仍是想和你们分享一点教训。例如不要使用浮点型数据,这是因为舍入会形成偏差,因此建议各位使用整形数据。一样,另外一个又被重视又被忽略的是随机数的问题。你们都知道帧同步要保证随机数也彻底一致。所以,你们都会去同步随机数生成器的种子和它们的使用方式。可是一个潜在的可能性是某一方的非游戏逻辑对象使用了随机数生成器,从而形成不一样步。例如某一方的移动设备性能更好,也所以屏幕上有一些额外粒子特效,这些粒子特效是有可能会使用随机数发生器的,若是这些游戏逻辑以外的对象使用了随机数发生器就会形成不一样步的发生。
哦,对了,最后须要说明的一点是帧同步还能够和C/S模型组合使用,咱们能够经过服务器来转发客户端的操做数据,而没必要让各个客户端直接通信。公司内有项目组采用的就是这种方案。

0x03 后记

固然,以上只是一些基本的同步模型。在这里只是结合咱们的项目经验和你们作一个简单的分享,我想基于这些基本的模型还会衍生出一些别的方案。也欢迎你们来一块儿交流。

欢迎你们关注个人公众号慕容的游戏编程:chenjd01
201701312351412651fGTISk.png

最后打个广告,欢迎支持个人书《Unity 3D脚本编程》~
686199-20160919193306199-2036072132.jpg

相关文章
相关标签/搜索