前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >网络游戏是如何实现对战的呢?本文告诉你

网络游戏是如何实现对战的呢?本文告诉你

作者头像
用户3147702
发布2022-06-27 16:39:04
2.6K0
发布2022-06-27 16:39:04
举报
文章被收录于专栏:小脑斧科技博客

1. 引言

前几天和同事聊起我之前做电商交易系统时,是如何保证订单数据的最终一致性的,聊到后来,想到一个有趣的问题,显然,对战类网络游戏对于数据一致性的要求更为苛刻,这些对战类网游中,是怎么保证玩家间数据的最终一致性呢?

经过查阅国外诸多大神的技术博客,参阅了起源引擎的官方文档,梳理出了这篇技术博客,希望能把这个有趣的问题讲清楚,还等什么,一块来看看吧!

2. 联机游戏的诞生

2.1 早期联机游戏

要是说起最早的联机游戏,那就不得不提大名鼎鼎的 SpaceWar,他是 1969 年由瑞克·布罗米在 1962 年同名游戏基础上制作的联机版本,如今在 steam 平台,每天都有 5000 人以上在同时游玩着它的 PC 移植版。

随后的几年时间里,麻省理工大学的 PLATO 系统吸引了很多开发者开发不同类型的游戏,比如风靡美国的 Avatar 和 Empire 都是诞生在这个系统上的经典之作。

这些当时最为火热的局域网联机游戏主要分为两类:飞行射击类与桌游模拟类,这其中,尤其以龙与地下城题材的桌游模拟类游戏最为丰富。

2.2 早期联机游戏的同步机制 – lockstep

只要是联机游戏,那么就必须要考虑同步机制,否则两个人在不同的屏幕上看到的游戏画面、游戏结果各不相同就没法把游戏进行下去了。

由于这些早期联机游戏都是建立在局域网内的,事实上,那个时候连 IP 传输协议还没有诞生,因此,他们普遍都采取了无中心化的网络连接方式 Peer-to-Peer,也就是我们今天所说的 P2P 网络的雏形。点对点之间互有连结资讯,彼此形成无规则网状拓扑结构,节点间以广播的方式进行通讯。

这些联机游戏受到传统桌游的启发,采用了类似于桌游的同步策略 – lockstep,这个词来源于步兵行进过程中整齐划一的步伐,国内翻译为“帧同步”,其主要思想一直沿用至今。

游戏按照“回合”来进行组织,在游戏领域,回合被称为“turn”,一个回合内,所有联机的玩家各自下达指令,然后这些指令通过广播的方式通知到所有正在联机的主机上,每个主机独立对这个回合的运算结果进行计算,然后将结果显示在用户的显示器上。

《Algorithms and Networking for Computer Games》一书中,详细介绍了 lockstep 的设计思想,每一次同步都分为 commit 和 reveal 两个阶段,commit 阶段中,各个主机将当前产生的指令提交广播,reveal 阶段中,主机将收到的所有指令进行计算、校验,从而得到最终的结果。

在实际的工作中,两个阶段类似 CPU 的多道流水线机制进行并发叠加就可以实现游戏的实时渲染了。

2.3 lockstep 的缺点

显而易见,这样的游戏同步方式存在几个问题:

  1. 所有主机的计算结果必须一致,因此不能有随机因素。
  2. 如果计算量过大,那么玩家必须等待。
  3. 不能中途加入游戏,也不能断线重连。
  4. 每台主机都拥有全部数据,即使客户端对敏感数据进行了隐藏,依然无法杜绝作弊的发生。

这就是为什么模拟桌游的 Empire 成为了当时最火热的游戏的原因,这类游戏本身就是通过一个个回合进行组织的,回合之间的等待是符合玩家预期的,而一次游戏必须是从头至尾不能中途加入的。

而另一类当时的联机游戏 – 射击类游戏,通常把画面的若干帧作为一个回合,由于它本身计算非常简单,只需要通过坐标的加减比较运算即可完成一个回合结果的运算,不会影响到玩家的正常操作,lockstep 也成为了同步算法的首选。

3. warcraft 对 lockstep 机制的改进

3.1 war3 的诞生

进入 20 世纪 70 年代,随着雅达利的崛起,家用游戏机市场的火爆让联机游戏淡出了人们的视野,即便是经历了雅达利大崩溃的洗礼,任天堂、世嘉与卡普空、SNK 在家用游戏机、街机市场硝烟四起的争战仍然让全世界的玩家都把目光集中到了主机游戏的领域中,可以说整个八九十年代,就是主机游戏的黄金时代。

到了 1994 年,暴雪娱乐公司推出了大名鼎鼎的《魔兽争霸》,这部对当时世嘉主机 MD 上大红大紫的《沙丘2》的跟风之作凭借着他首开先河的推出即时战略联网模式成为了多人模式即时战略游戏的鼻祖。

2002 年,掀起全球电子竞技热潮的 warcraft3 问世,直到今天,游戏圈的同仁们每每回想起 2005 年 WCG 三冠王 sky 李晓峰首次韩国赛场上披着五星红旗呼喊的画面,仍然会热泪盈眶。

那么,这部主打联机对战的 RTS 游戏是如何实现他的同步机制的呢?我找到了一篇介绍联机游戏同步机制的博文:

https://gafferongames.com/post/what_every_programmer_needs_to_know_about_game_networking/

在他的评论区,有人给出了 war3 同步机制的介绍。

3.2 war3 的同步机制 – Lockstep 与 C-S 模式结合

1997 年,由全效工作室开发的《帝国时代》系列首作问世。

这部优秀的作品同样支持网络联机,然而,联网玩过帝国时代的玩家都知道,在游戏联机过程中,只要有一个人的网络出现延迟,所有玩家的画面都会出现暂停。这是因为《帝国时代》采用了上文中所介绍的 lockstep 同步方式造成的,下面的文章详细介绍了《帝国时代》的同步策略:

https://www.gamasutra.com/view/feature/131503/1500_archers_on_a_288_network_.php

在游戏的每个回合操作之后,当前主机向其他主机发出操作指令的广播,并且等待和汇总各个主机的运算结果,只有收集到所有主机的运算结果后,才可以进入到下一回合的进行。这就造成了所有主机等待一台主机的情况发生。

那么,war3 是怎么避免这个问题的呢?

warcraft3 在采用 LockStep 同步模型的基础上,还加入了 client-server 同步模式,在所有联机的局域网客户端中,会选举出一个主机,主机的主要功能是广播并设置 timeout,每个回合包含固定的帧数,每个回合都有超时时间,在超时时间内,每个玩家都将自己的操作指令发送给主机,主机等待时间到达 timeout 后,则不再处理上一回合的操作,此时尚未给主机发送操作数据的玩家也就是我们常说的“掉线玩家”,主机认为“掉线玩家”就是未进行任何操作的玩家,然后主机将收集到的操作广播给局域网内其他的玩家,这些收到指令的客户端回放操作即可。

3.3 同步模式与游玩体验

基于 c-s 与帧同步的同步方式很大程度上解决了《帝国时代》等游戏中,一个人网络慢,所有人停下来等他的问题,玩过 war3 的人应该会有体会,当你的网络卡顿时,只有你的客户端上运行缓慢甚至静止,其他玩家的体验并不会受到影响,除非你的客户端恰巧是被选举出来的主机。但当你的网络恢复时,你会发现你的游戏画面仿佛开了倍速播放,游戏单位以非常快的速度执行着操作,这是因为由于网络恢复,客户端收到了之前断开连接期间所有 turn 的指令集合,客户端为了赶上进度,就会出现游戏快放的情况。正如我们前文所说的,LockStep 同步机制有着显而易见的三大问题,war3 又是如何解决的呢?

3.3.1 随机事件回放

首先,为了所有参与游戏的客户端在回放操作时都能计算出同样的结果,游戏中就不能有完全随机的事件发生,众所周知 war3 中拥有大量的随机运算,他是怎么实现的呢?我们知道,大部分编程语言内置库里的随机数都是利用线性同余发生器产生的,只要指定相同的随机种子,那么生成的随机数就完全是确定的。每当游戏开始前,参与游戏的玩家电脑就会协商确定一个随机种子,从而保证对同一操作的计算结果一致。

3.3.2 回放过程与计算量

在实际的游玩过程中,我们很难体会到“回合”,那是因为每个回合都只有 100 毫秒,且由于回合之间的操作非常少,同步和运算工作量是极小的,所以人很难感知到,即便是 war3 职业玩家,每分钟操作数(APM)也不过是三四百而已,平均每个回合只有一个指令触发,对于主机和其他玩家客户端的运算是毫无压力的,同时,即使网络有延迟,由于玩家的主要工作都是对整个战局的思考与观察,如果不是双方大规模单位的交战场景,玩家也并不会体会到短暂延迟的发生。

warcraft3 的 replay 机制也同样是通过记录操作、回放操作、校验结果来实现的,这就大幅缩小了 replay 文件所需要占用的空间,这也是为什么如果在错误的客户端版本上播放 replay 会造成 replay 过程的混乱,同时 war3 不允许 replay 播放过程中任意选定时间点开始播放。

当然,任意拖动进度条并非不能解决,只要从头计算出当前进度条位置的全部状态即可,这就是为什么在 starcraft2 中,如果你在播放 replay 时拖动进度条,有时会需要等待很久的原因。

3.3.3 游戏作弊问题

为什么各平台对于 war3 游戏的外挂屡禁不止,尤其是开图挂,正是因为每个客户端的内存中都拥有所有数据,在这样的同步模式下,是没有办法解决的,而所谓的对战平台也只是采用虚拟局域网(VLAN)技术,通过进程注入,HOOK WinSock 函数调用,模拟局域网环境而已,与局域网联机本身并没有区别。

对战平台能做的,只能是通过监控内存中 war3 的运行数据,从而发现他们被外部修改而识别外挂,并不能从根本上杜绝。

4. FPS 游戏中的网络同步

传统的各类 RPG、RTS 游戏根据游戏本身的规则和性质都可以轻松划分出一个个回合来实现上述帧同步的同步模式,同时,早期游戏的局域网环境,也更加适合帧同步这种无中心化的网络组织方式。

但正如上文所说,帧同步有着先天难以解决的几个问题,尤其是对于激烈对战的 FPS 游戏来说,同一场游戏中参与的玩家数量更多,而每个玩家玩家每时每刻都在紧密关注着对手的动态,同时,玩家本身输入的指令更为密集,即便网络仅仅是几毫秒的抖动,屏幕上对手的移动就会出现几英寸的误差,从而让玩家下意识的判断出现错误,严重影响到游玩体验。更为关键的是,大量且复杂的实时战斗数据对于玩家的主机性能要求过高,在这样的情况下,传统的 LockStep 同步策略显然无法满足玩家快节奏的需求。

起源引擎的官方文档中介绍了在这类游戏中,起源引擎是如何设计的:

https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking https://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization

4.1 C-S 同步模型

基于起源引擎的游戏网络同步架构使用的是 client-server 模型,由 server 负责对战斗核心逻辑及数据进行实时运算,而每个玩家的客户端则仅负责游戏场景的表现。

如下图所示,C-S 同步模型分为 ArenaServer 与预表现层两部分,蓝色的 ArenaServer 负责在服务端进行战斗逻辑与数据的实时运算,而浅绿色的预表现层则负责处理玩家的输入数据、与服务端进行交互,并实时运算需要被渲染的战斗场景,最终将渲染的场景数据交给作为展示层 ArenaRender 来处理并展示出来。

4.2 多人对战网络交互

在实际工作中,客户端以每秒 20 到 30 个数据包的频率向服务端发送数据,这些数据包含用户的操作数据以及麦克风等外设的采集数据。

服务端在接收到客户端的高频数据后,以固定频率(通常是以 15ms 为周期)运算出当前游戏世界的状态快照,然后通过广播发送给每一个正在游戏中的客户端。

然而,可想而知,服务端的高频快照总是会慢于客户端的实际情况,加上网络丢包不可避免的发生,客户端难以保证整个交互过程的稳定。

4.3 网络延迟的解决

4.3.1 输入预测

按照上述的同步模式,如果一个玩家的网络 ping 延迟是 150ms,当他在一次同步后立即做出操作,这些操作会延迟 75ms 到达服务端,并经由下一次快照下发到客户端,渲染到用户的显示器上,玩家会发现自己的动作延迟了 150ms,这显然是不可接受的。

因此,在玩家做出操作后,客户端在与服务端通信的同时,本地会有一套与服务端规则完全相同的运算规则,来实时计算玩家操作后的结果,由于本地的快速运算,玩家立即看到了操作带来的反馈,之后,当客户端再次受到游戏世界的快照数据后,再做出相应的微调,纠正客户端运算可能与服务端之间存在的误差。

玩过 CS online 或 CF 等网络对战的 FPS 游戏的玩家都会有一种体会,在网络状况不太好时,自己有时会感觉到角色的突然瞬移,或者已经射杀的对手突然复活等情况的出现,这正是输入预测机制带来的影响。

4.3.2 滞后补偿

由于客户端与服务端的通信是非连续的,且存在不可避免的滞后性,因此,服务端需要对实际接收到已经滞后的数据包进行补偿运算,来判定两个包之间发生的事。

典型的情况如上图所示,画面中清晰的显示了玩家与对手的位置,在延迟 200ms 的情况下,服务端模拟出到当前世界的快照后,需要通过回放出玩家进行攻击操作时对手所在的位置,红色框为玩家客户端通过输入预测计算出的对手模型,而蓝色框为服务端通过滞后补偿的一系列算法计算出的对手所在位置,由于玩家操作指令所射击的位置与服务端滞后补偿计算出的对手所在位置吻合,于是这样就验证了客户端的命中消息。

但在弱网环境中,延时可能非常巨大,服务端通过滞后补偿算法可以计算出客户端实际可能存在的多种可能性,从而让客户端有漏洞可钻,有一些开发者通过操作系统提供的网卡流量控制等方式模拟弱网环境,故意让客户端在较长时间间隔内不上报数据,然后通过修改客户端内存中的数据,让客户端上报修改后的数据,或者干脆通过中间人攻击等方式直接上传篡改后数据,从而实现瞬移、命中率100%等作弊操作。

5. MOBA 网络游戏中的网络同步

显然,MOBA 游戏更接近于传统的 RPG 与 RTS 游戏,所以,他们大部分都采用了 LockStep 模式为主,C-S 模式结合的同步模式。

客户端仍然以 100 到 200 毫秒的频率上报操作数据,并模拟执行操作的结果,服务端实时运算结果同步给客户端来进行修正。

现代网络游戏中,你在进入游戏之前,往往要选择网络延迟最低的服务器集群来进行交互,即使你没有手动选择,游戏客户端往往也会通过检测结果自动选择相应的服务器集群,从而保证所有玩家都在相对最佳的网络环境中进行游戏。

而同时,MOBA 类游戏中,每个魔法的施放其实都有一定的前摇动画和施法结束的后摇动画,虽然这个动画在介绍中有规定的时间长度,但在实际游玩过程中,玩家并不会在乎这个动画是否比预期长了一些或短了一些,这就为客户端与服务端通信后模拟数据的修正以及网络通信延迟的发生留有了余地。

参考资料

https://gafferongames.com/post/what_every_programmer_needs_to_know_about_game_networking/

http://www.diva-portal.org/smash/get/diva2:347749/FULLTEXT01.pdf

https://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization

https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking

https://www.gamasutra.com/view/feature/131503/1500_archers_on_a_288_network_.php

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小脑斧科技博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 引言
  • 2. 联机游戏的诞生
    • 2.1 早期联机游戏
      • 2.2 早期联机游戏的同步机制 – lockstep
        • 2.3 lockstep 的缺点
        • 3. warcraft 对 lockstep 机制的改进
          • 3.1 war3 的诞生
            • 3.2 war3 的同步机制 – Lockstep 与 C-S 模式结合
              • 3.3 同步模式与游玩体验
                • 3.3.1 随机事件回放
                • 3.3.2 回放过程与计算量
                • 3.3.3 游戏作弊问题
            • 4. FPS 游戏中的网络同步
              • 4.1 C-S 同步模型
                • 4.2 多人对战网络交互
                  • 4.3 网络延迟的解决
                    • 4.3.1 输入预测
                    • 4.3.2 滞后补偿
                • 5. MOBA 网络游戏中的网络同步
                • 参考资料
                相关产品与服务
                流计算 Oceanus
                流计算 Oceanus 是大数据产品生态体系的实时化分析利器,是基于 Apache Flink 构建的企业级实时大数据分析平台,具备一站开发、无缝连接、亚秒延时、低廉成本、安全稳定等特点。流计算 Oceanus 以实现企业数据价值最大化为目标,加速企业实时化数字化的建设进程。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档