聊聊网络游戏同步那点事

写的非常好的一篇博文,转载自https://www.cnblogs.com/murongxiaopifu/p/6376234.html

0x00 前言

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

0x01 游戏同步中的主次

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

例如,我们之前开发的单机版本并不需要多么担心作弊的问题。这是因为购买我们游戏的玩家(假如我们的单机游戏不免费发布的话)即便作弊,影响的也仅仅是他自己的游戏体验,不会影响到别人。

但是开发多人游戏就不是这样了,为了保证让每个人都有好的游戏体验,防止作弊总是需要去考虑的。

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

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

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

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

0x02 同步输入or同步状态

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

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

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

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 后记

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/246207.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity 2017 Game Optimization 读书笔记 Dynamic Graphics(1)

The Rendering Pipeline 渲染表现差有可能取决于CPU端(CPU Bound)也有可能取决于GPU(GPU Bound).调查CPU-bound的问题相对简单,因为CPU端的工作就是从硬盘或者内存中加载数据并且调用图形APU指令。想找到GPU-bound的原因会困难很多&#xff…

Unity 2017 Game Optimization 读书笔记 Dynamic Graphics(2)

Lighting and Shadowing 现代的游戏中,基本没有物体能在一步就完成渲染,这是因为有光照和阴影的关系。光照和阴影的渲染在Fragment Shader中需要额外的pass。 首先要设置场景中的Shadow Casters和Shadow Receivers,Shadow Casters投射阴影&…

Unity 2017 Game Optimization 读书笔记 The Benefits of Batching

batching(合批) 和大量的描述一个3D物体的数据有关系,比如meshes,verices,edges,UV coordinates 以及其他不同类型的数据。在Unity中谈论batching,指的是用于合批mesh数据的两个东西&#xff1a…

Unity 2017 Game Optimization 读书笔记 Dynamic Graphics (3)

Rendering performance enhancements Enable/Disable GPU Skinning 开启GPU Skinning可以减轻CPU或GPU中Front End部分中某一个的负担,但是会加重另一个的负担。Skinning是mesh中的顶点根据动画中骨骼的当前位置进行计算,从而让角色摆出正确的姿势。 …

Unity手游开发札记——布料系统原理浅析和在Unity手游中的应用

原文:https://zhuanlan.zhihu.com/p/28644618 0. 前言 项目技术测试结束之后,各种美术效果提升的需求逐渐成为后续开发的重点,角色效果部分的提升目标之一便是在角色选择/展示界面为玩家提供更高的品质感,于是可以提供动态效果的…

行为树(Behavior Tree)实践(1)– 基本概念

原文:http://www.aisharing.com/archives/90 行为树(Behavior Tree)实践(1)– 基本概念 自从开博以来,每天都会关心一下博客的访问情况,看到一些朋友的订阅或者访问,不胜欣喜&…

Unity 2017 Game Optimization 读书笔记 Dynamic Graphics (5) Shader优化

Shader optimization Fill Rate和 Memory Bandwidth开销最大的地方就是Fragment Shader。开销多大取决于Fragment Shader的复杂程度:多少纹理需要采样,多少数学计算函数需要使用等等。GPU的并行特性意味着在线程中如果任何地方存在瓶颈,都会…

Unity 2017 Game Optimization 读书笔记 Dynamic Graphics (6)

1. Use less texture data 这条优化技巧非常直接,减少texture的数据量,减少分辨率或者降低位数,虽然可能会降低渲染质量。但是通常使用16-bit textures并不会明显的感觉到渲染效果下降。 MipMap技术可以有效减少VRAM和Texture Cache之间来回…

LeetCode 面试题57 - II(剑指offer) 和为s的连续正数序列

今天毕业五年了,一直忙于工作和享受,自从当年找完工作后就一直没有再刷过题,作为搬砖的码农,觉得还是应该养成长期刷题的习惯坚持下去。之前坚持了每天被一会单词,如今雅思一本也快看完了,从今天开始准备在…

反走样技术相关文章

https://zhuanlan.zhihu.com/p/28800047 https://zhuanlan.zhihu.com/p/57503957 https://zhuanlan.zhihu.com/p/33444125 https://zhuanlan.zhihu.com/p/33444429 走样的原因及其分类 说到走样,首先要说的就是采样。这也算是很多图形学专著中提到反走样相关技…

求n的阶乘的算法框图_单片机常用的14个C语言算法

问:怎么每天看到这种文章?答:只需搜索公众号"51单片机学习网"免费关注算法(Algorithm):计算机解题的基本思想方法和步骤。算法的描述:是对要解决一个问题或要完成一项任务所采取的方法和步骤的描述&#xff…

LeetCode 286. 墙与门 多源BFS和DFS

思路1&#xff1a; DFS&#xff0c;对于每个门进行一次DFS搜索&#xff0c;记录每个位置对每个门的距离&#xff0c;当有更小距离的门时更新这个数值 public void WallsAndGates(int[][] rooms) {for (int i 0; i < rooms.GetLength(0); i){for (int j 0; j < rooms[i]…

贝塞尔曲线

文章参考于&#xff1a;https://www.jianshu.com/p/0c9b4b681724 https://gameinstitute.qq.com/community/detail/129188 贝赛尔曲线的前世今生&#xff1a; 贝塞尔曲线&#xff0c;这个命名规则一眼看上去大概是一个叫贝塞尔的数学家发明的。但&#xff0c;贝塞尔曲线依据…

如何控制局域网网速_单臂路由|N1盒子(OpenWRT)单线多拨实现网速叠加

受于某些现实条件&#xff0c;有些同学苦于家里的网络带宽太小无法尽情冲浪。如何在不额外花钱升级宽带的情况下提升家里网络呢&#xff1f;且看一个盒子加路由器即可实现网络单线多拨&#xff0c;成倍提升网速完成网速叠加。题图是我家里的路由器加N1盒子。前置条件光猫有超级…

linux离线安装redmine_Linux 下一款非常好用的翻译软件

前面有一个半月的时间&#xff0c;我非常详细且非常基础的介绍了 Ubuntu 18.04 desktop 桌面系统的安装和基本使用&#xff0c;在知乎上也开了一个专栏《Linux 漫游之旅》&#xff0c;上面记录了所有的文章&#xff0c;这个专栏的目的呢是手把手教新接触 Linux 操作系统的朋友如…

vivo应用商店电脑版_VIVO应用商店代理商江湖的那些关系

VIVO应用商店代理商江湖的那些关系需要源文件清晰版本加微信wps007其他干货文章如何不花钱或者少花钱把ASO的活给干了&#xff1f;2020最新主流安卓应用市场ASO技巧以及注意事项App推广的高阶玩法&#xff0c;一箭双星&#xff01;今日头条定向优化技巧今日头条广告创意优化指南…

华为阅读下载的文件在哪里找_华为手机还要天天清理内存?1键关闭这2个设置,手机用到2035年...

阅读本文前&#xff0c;请您先点击上面的蓝色字体“科技荟 ”&#xff0c;再点击“关注”&#xff0c;这样您就可以继续免费收到最新文章了。每天都有分享。完全是免费订阅&#xff0c;请放心关注。 华为手机还要天天清理内存&#xff1f;1键关闭这2个设置&#xff0c;手机用到…

pyautogui 打包 运行 窗口_试试动态窗口管理器 dwm 吧

以不到 2000 标准行的代码写就的 dwm&#xff0c;是一个速度极快而功能强大&#xff0c;且可高度定制的窗口管理器。-- Adam Šamalk(作者)如果你崇尚效率和极简主义&#xff0c;并且正在为你的 Linux 桌面寻找新的窗口管理器&#xff0c;那么你应该尝试一下 动态窗口管理器(dy…

ArcMap 导入 wrl_flmic拍摄的素材如何无损导入电脑

点击上方“九尾短视频研习室” 可以订阅哦&#xff01;今天分享使用 iPhone 或者安卓版 filmic 拍摄的素材&#xff0c;如何无损导入到win 或 Mac 电脑中~01iPhone Mac使用 iPhone 和 Mac 的朋友&#xff0c;可以使用“隔空投送”无线传输&#xff0c;但是这个过程中&#xff…

LeetCode 97: 交错字符串

这里我们考虑用 s1和 s2的某个前缀是否能形成 s3 的一个前缀。 这个方法的前提建立于&#xff1a;判断一个 s3的前缀&#xff08;用下标 k表示&#xff09;&#xff0c;能否用 s1和 s2 的前缀&#xff08;下标分别为 i和 j&#xff09;&#xff0c;仅仅依赖于 s1 前 i个字符和…