了解Edgegap的工作原理

了解Edgegap的工作原理

网络代码基础:Ping、滴答率(Tick Rate)与网络模型详解

已发布

已发布

已发布

Edgegap 洞察系列横幅,上面写有“网络代码基础”(Netcode Fundamentals),并配有一个瀑布图预览,展示了一名玩家的输入与另一名玩家屏幕显示之间,网络、服务器和客户端延迟是如何累加的。

核心洞察

核心洞察

核心洞察

  • 延迟存在下限,其他一切因素都在其之上累加:两台机器之间的物理传输时间是任何网络游戏所能拥有的最小延迟。路由、Tick率、更新率以及处理过程都会增加延迟。网络代码无法消除这种延迟,它只能决定玩家在何处感受到它。

  • 最短路径很少是最快的:直接的P2P(点对点)连接看起来是两名玩家之间的最短路线,但数据包仍需经过两名玩家的互联网服务提供商(ISP)以及这些网络所选择的任何路由。在他们之间设立一个位置合理的服务器,往往既更快又更公平。

  • 延迟补偿转移了代价,而不是消除了代价:延迟补偿会回溯服务器状态,以使高Ping玩家的射击有效,这意味着目标在到达掩体后仍可能被击中。唯一的真正解决办法是缩小Ping值差距,这使得它既是一个网络代码问题,也是一个匹配机制和服务器部署问题。

  • Tick率就是时间预算:服务器的Tick率设定了它模拟游戏每个步骤所拥有的毫秒数。更高的速率可以减少延迟并提高命中判定精度,但会消耗更多的CPU和带宽。超出预算的服务器会导致对局中的每个人都发生卡顿。

  • 这是两个独立的选择,而非一个:游戏在哪里运行(P2P、中继或专用服务器)与状态如何共享(锁步同步、回滚同步或状态复制)是相互独立的决策。任何同步模型都可以在任何托管模型上运行。

这是一篇关于在线多人游戏网络代码(Netcode)构建基块的基础读物。在整篇文章中,我们为每个术语链接了词汇表定义,并附带了后台深度剖析(Backend Deep Dive)文章,以展示这些概念如何在知名的多人游戏中得到应用。

什么是网络代码(Netcode)?

网络代码是保持多人比赛在相隔数毫秒的机器之间保持一致的联网代码。它并不是孤立工作的。网络代码是更广泛生态系统中的一层,与服务器托管、编排和匹配一起,共同提供在线多人游戏体验。我们的《使命召唤》网络代码文章展示了这些层在实时游戏中的交互方式。

网络代码本身分为七个部分:

Waterfall diagram titled "Where the Milliseconds Go", tracing one player input to another player's screen in eight steps: travel to server, routing detours, wait for next tick, simulate, wait for next send, travel to other player, routing detours, and interpolation buffer. Each step starts where the last one ended, and a total delay bar shows them combined. Physical travel is the minimum delay set by distance. Routing is reduced by server placement, the server clock by tick and update rate, and client smoothing is tuned by netcode. Note: for illustration only, not to scale.

客户端/服务器(C/S)网络代码的起源

大多数现代射击游戏其网络代码都可以追溯到一款游戏。原版《雷神之锤》(Quake, 1996)使用了纯粹的客户端/服务器设计:客户端将他们的输入发送到服务器,然后等待服务器告诉他们发生了什么。每个客户端只是一个显示服务器世界的终端。

在局域网上,这种设计行得通。但在互联网上,它失效了。

时任 id Software 首席程序员的约翰·卡马克(John Carmack)在其 1996 年 8 月的开发日志中写道,他“在进行优质互联网游戏时采用了错误的基准假设”。最初的设计“针对的是小于 200 毫秒的连接延迟”,而调制解调器(Modem)玩家看到的“延迟至少在 300 毫秒以上”。在纯客户端/服务器模式下,每一次按键都需要等待一个完整的往返时间,屏幕上的画面才会移动。

他对 QuakeWorld 的修复确立了沿用至今的模型。客户端现在会“预测用户移动的结果,直到来自服务器的权威响应通过”。服务器保持权威性,客户端进行预测。

在同步模型(下文将介绍)中,QuakeWorld 使用了状态复制:服务器发送游戏世界状态,每个客户端预测自己的移动,直到下一次更新到达。这不同于帧同步,在帧同步中,每台机器必须等待其他所有人的输入才能向前推进。

这种结合了权威服务器和客户端预测的模式,成为了其他人构建系统的基石。《部落》(TRIBES, 1998)增加了同步的 32 毫秒滴答、其他玩家的插值,并在三个连续的数据包上发送输入。二十年后,《守望先锋》(Overwatch)仍在使用一种可滑动的输入窗口,其开发人员表示这可以追溯到 QuakeWorld。

什么是 Ping,它与延迟(Lag)有什么不同?

Ping 是一种测量值。你的机器向另一台机器发送一条简短的消息,后者进行回复,发送和接收之间的时间就是往返时间(RTT)。如需适合初学者的入门读物,请参阅 Edgegap 关于游戏中的延迟是什么的指南。

Lag(滞后)则是后果。它是你在屏幕上看到的内容与服务器以及其他所有玩家在其屏幕上看到的内容之间的差距。

Lag 也不仅仅是一种感觉。在 Edgegap 的延迟报告中,50% 的玩家将滞后列为他们玩在线游戏时的第一大挫败来源,34% 的玩家表示他们曾因此彻底退游。

任何网络代码都无法突破一个底线。数据在铜线和光纤中以有限的速度传输,因此延迟永远不可能低于两台机器之间的传输时间。其他所有因素都是在这一底线之上累加的。

最大的累加因素通常是路由。数据包从不以直线传播。它们经过由不同网络拥有的路由器链,每一次跃点(Hop)都会增加时间。这就是为什么分布式云基础设施要从服务器的物理位置开始布局的原因。

这也是直觉容易出错的地方。在双人比赛中,直接的对等(P2P)连接看起来像是最短的路径。中间没有服务器,只有玩家到另一个玩家。

但在实践中,“直接”仍意味着离开一个玩家的家庭网络,穿过其 ISP(互联网服务提供商),穿过另一个玩家的 ISP,最后到达可能使用 Wi-Fi 的消费级连接。如果加入更多玩家,其中一人就必须担任主机(Host),这导致主机实现零延迟,而其他所有人面临不同的延迟。在所有玩家之间合理放置一台中心化服务器可以消除主机的优势,并且通常能缩短实际路由。下一节将解释原因。

为什么单凭距离无法预测 Ping?

两名相距仅 50 公里的玩家之间仍可能存在糟糕的连接。关键在于他们数据包实际行进的路线。

拳头游戏(Riot Games)的工程团队在 2015 年构建自己的游戏网络时记录了这一点。他们解释说,骨干网提供商和 ISP“优先选择更便宜的路线,而不是更快的路线”。在一条旧金山到波特兰的连接上,“直连可能只需要 14 毫秒,但效率较低的路线需要整整 70 毫秒”。

距离决定了底线。而路由决定了你会在底线之上高出多少。

同样的逻辑也适用于选择服务器位置。目标不是靠近某一个玩家。目标是找到能让比赛中的每位玩家获得最佳、且最均衡连接的地点。

Edgegap 与一家前 5 名发行商合作进行的 1v1 格斗游戏案例研究对此进行了衡量。通过在最佳可用位置按需部署每场比赛的服务器,而不是使用固定的公共云区域组,对手之间的延迟差距从 46.5 毫秒缩窄至 33 毫秒,公平性提高了 28%。91% 的玩家看到了更低的延迟。

这就是拥有更多位置的合理性所在:服务器可以启动的位置越多,越有可能有服务器处于适合所有人的短而均衡的路由上。为此,Edgegap 的网络现在已覆盖全球 615 多个位置。

为什么一个高 Ping 玩家会影响所有人?

在射击游戏中,高 Ping 玩家瞄准的是他们看到的靶子位置,但这已经是过去了。如果服务器仅根据当前状态判定击中,那么该玩家几乎永远无法击中目标。

延迟补偿通过“倒带”来解决这个问题。当一发子弹到达时,服务器会将其他所有玩家移回到射击者开枪时他们所在的位置,然后在那时进行击中判定。

这很有效。但也伴随着代价。时任 Valve 开发人员的雅恩·贝尔尼埃(Yahn Bernier)在其 2001 年关于延迟补偿的论文中这样描述:当“一个高延迟的玩家射击一个低延迟的玩家并得分时,在低延迟玩家看来,高延迟玩家似乎以某种方式‘隔墙击中’了自己”。

低延迟玩家在自己的屏幕上已经进入了掩体。但经过倒带的服务器却判定他们没有。

各工作室对这种权衡的调整不尽相同。《APEX 英雄》刻意在低 Ping 和高 Ping 玩家之间均摊这种“荒谬情况”,接受 300 毫秒延迟的玩家可能会在掩体后被射中的事实。《无畏契约》(VALORANT)估计,玩家从角落探头时大约有 141 毫秒的先手优势,并围绕缩小这一优势构建了其滴答率、缓冲和路由。当差距变大时,两者都会表现为不同步和回弹(Rubberbanding)。

没有任何延迟补偿设置可以解决巨大的 Ping 值差距。保持差距较小才是解决之道,这也是为什么匹配机制中应考虑延迟的原因。Edgegap 的匹配器为此包含了延迟规则,我们的通过匹配提高延迟表现指南介绍了这种方法,同时还涵盖了电子竞技中公平性与延迟的关系。

什么是滴答率(Tick Rate)和更新率(Update Rate)?

每个游戏服务器上都运行着两个时钟,它们经常被混淆。

  • 滴答率(或模拟率)是服务器每秒处理输入和推进游戏世界的次数。

  • 更新率(或发送率)是服务器每秒向客户端发送结果的次数。

它们通常相等,但许多引擎会将其解耦。

每个滴答(Tick)都是一个固定的时间预算。换算非常简单:用 1000 除以赫兹率即可。

滴答率

每个滴答的时间

示例

20 Hz

50 ms

《APEX 英雄》

~31 Hz

32 ms

《部落》(1998)

60 Hz

16.67 ms


64 Hz

15.625 ms


128 Hz

7.8125 ms

《无畏契约》

滴答间隔在网络延迟之外又增加了延迟。平均而言,一个输入在服务器处理之前要等待大约半个滴答,因此从 64 Hz 提升到 128 Hz 可以将该等待时间从大约 7.8 毫秒减少到 3.9 毫秒。

无法在预算时间内完成工作的服务器将会落后。在《APEX 英雄》中,如果服务器错过了 50 毫秒的窗口,会导致整场比赛在物理、动画和复制进行追赶时出现卡顿。玩家会看到回弹、瞬间移动和判定无效。

低更新率会导致更奇怪的异常。独立分析师 Chris(Battle(non)sense YouTube 频道创办者)在其 2017 年的“Netcode 101”视频中解释了“超级子弹”(Super Bullet)现象。在每秒 10 次更新的速率下,每个数据包之间相隔 100 毫秒,这与一把每分钟射速 600 发的枪射击两发子弹之间的间隔相同。如果一把枪的射速为 750 RPM 或更快,则会将两发或更多子弹放入一次更新中,因此受害者受到的伤害看起来像是一次性承受了超过一发子弹所能造成的伤害。

更高的滴答率可以减少延迟并提高命中判定精度。但它们也会增加每场比赛消耗的 CPU,而且当更新率随之上升时,还会消耗更多带宽。有关完整的权衡分析,请参阅游戏服务器滴答率详解。

游戏在哪里运行?托管模式

第一个结构性选择是权威模拟运行的位置。大致有三种选择。

对等网络(玩家托管)。 一个玩家的机器充当主机,或者各个对等方直接连接。这不需要服务器账单。作为交换:

  • 主机玩家在游玩时没有任何网络延迟,而其他所有人都取决于主机的家庭上传速度。

  • 当主机退出时,会话结束,或者在另一个玩家接管时暂停。请参阅 Edgegap 关于对等或中继游戏中的主机迁移指南。

  • 直接连接会将每个玩家的 IP 地址暴露给会话中的其他人。

  • 判定权在玩家的机器上,因此该玩家可以篡改游戏状态。

中继(Relay)。 中继服务器在对等方之间转发数据包。它隐藏了玩家的 IP 地址,并帮助连接通过受限的家庭网络。它不运行模拟或进行任何验证,因此对等网络的判定权问题依然存在。

专用服务器(Dedicated Server)。 模拟运行在开发商控制的机器上。客户端发送输入,服务器决定发生了什么。这消除了主机优势和主机迁移问题,并为每位玩家提供了一个中立的连接点。其权衡在于成本和覆盖范围:必须为服务器付费,并且它们必须离每位玩家足够近,以保持合理的 Ping 值。

许多游戏混合使用不同的模式。《命运 2》(Destiny 2)将对等网络与权威服务器结合使用。像 Edgegap 的游戏服务器托管这样的编排平台,旨在根据每场比赛的需要,在比赛附近按需启动专用服务器,而不是在少数几个地区维持闲置的服务器集群。有关主要网络代码库如何支持每种模型,请参阅7 种网络代码集成方式。

游戏状态如何共享?同步模型

第二个选择是机器之间如何保持一致。这独立于托管模式:以下每种方法都可以通过对等网络或专用服务器运行。

帧同步(输入延迟 / Lockstep)。 机器之间仅交换输入,每台机器运行相同的确定性模拟。在每个步骤中,只有在所有人的输入都到达后,才会继续向前推进。它消耗的带宽非常少,而且每个屏幕上显示的内容完全一致。其代价是输入延迟等于网络延迟,且模拟必须在不同的硬件上具有完美的确定性。这在策略游戏中很常见。

回滚(Rollback)。 每台机器预测其他玩家的输入并立即进行模拟。当真实的输入到达且不一致时,游戏会回滚到该帧并重新向前模拟。操作感觉是即时的,代价是偶尔会出现画面修正和额外的 CPU 开销。这是格斗游戏中的标准做法,而且它同样适用于专用服务器:《以太之战 2》(Rivals of Aether 2)在 Edgegap 上将回滚网络代码与专用服务器进行了结合。Edgegap 对输入延迟与回滚的对比以及其回滚网络代码指南对此进行了深度剖析。

状态复制(State Replication)。 服务器发送世界快照,客户端使用四种技术来隐藏延迟:

  • 客户端预测: 客户端立即应用自己的输入,即 QuakeWorld 的思路。

  • 服务器核对: 当服务器的应答到达时,客户端纠正其预测,并重新播放服务器尚未处理的任何输入。

  • 实体插值: 其他玩家的呈现画面会略微滞后于过去,并在接收到的两个快照之间进行平滑过渡。

  • 延迟补偿: 服务器通过倒带来判定击中,如上文所述。

这是射击游戏的标准配置,从《部落》到《无畏契约》皆是如此。每种技术都是在用一种异常现象换取另一种:预测会带来修正,插值会增加延迟,而延迟补偿则会产生掩体后被射中的瞬间。

丢包对游戏有什么影响?

互联网并不保证送达。数据包会因 Wi-Fi 干扰、链路拥堵、硬件故障和路由器过载而丢失。正如我们的《APEX 英雄》深度剖析所指出的,丢包并不总是开发人员的错。

这就是为什么实时游戏使用 UDP 而不是 TCP 的原因。TCP 保证每个数据包按顺序到达,因此当一个数据包丢失时,它后面的所有内容都要等待它被重新发送。对于游戏来说,这意味着在连接恢复期间,角色会冻结在移动过程中。UDP 则让游戏来决定什么才是关键的:丢失的位置更新只需直接被下一个更新替换即可。

在低更新率下,丢失数据包带来的损害也更大,因为每个丢失的数据包都会留下一个更大的空白。游戏通过冗余来抵御丢包。《部落》在三个连续的数据包上发送每个玩家的输入。《守望先锋》将所有未确认的输入打包到每个数据包中,以便下一个数据包在服务器进行模拟前填补任何空白。

各个环节如何协同工作

上述每一个概念都在管理一个数字:从一个玩家执行操作到其他所有玩家看到该操作之间的时间。

物理距离和路由设定了起点。滴答率和更新率增加了它们自身的延迟。托管模式决定了谁来承担这些差异,而同步模型决定了这在屏幕上呈现为何种效果。

这就是为什么在我们的深度剖析中,几乎每款游戏都会遇到相同的问题。答案因游戏而异。但问题是一样的。

其中许多答案都可以归结为服务器在何处以及何时运行。跨分布式网络自动进行混合编排,将用于稳定流量的裸金属与用于应对流量峰值的云容量相结合,可以让同一种方法服务于非常不同的游戏,从大型 MMO 到每个服务器运行多个对战房间的轻量级移动游戏。要了解其工作原理,请阅读关于 Edgegap 游戏服务器编排的更多信息。

来源

本文基于并引用了“来源”中所列的作品。原始内容的所有权利归其各自所有者所有。

书写者

菲利普·科特 (Philip Côté) (首席技术官),雅库布·莫蒂尔 (Jakub Motyl) (产品负责人),加布里埃尔·帕伦特 (Gabriel Parent) (总监)

Get your Game Online Easily & in Minutes

立即开始集成!

轻松在线游戏
且在几分钟内

Get your Game Online Easily & in Minutes