了解Edgegap的工作原理

了解Edgegap的工作原理

Netcode

网络代码(Netcode)是多人游戏用于保持每位玩家对比赛画面看法一致的网络技术集合,尽管他们之间存在延迟。它涵盖了服务器发送的内容和频率、客户端在期间预测的内容以及如何解决分歧。它是玩家在看不到的情况下能感受到的那一层。

由

由

由

雅库布·莫蒂尔

雅库布·莫蒂尔

雅库布·莫蒂尔

,

产品总监

产品总监

产品总监

已发布

已发布

已发布

网络代码是由什么构成的?

玩家所谓的“网络代码差”,大多数情况下只是一种表象,而根源通常在与被埋怨的层级不同的另一个层级。本页面将介绝网络代码的构成。它以什么为代价进行交易,以及如何判断是哪一层出乆了问题。

网络代码(Netcode)是一种网络编程代码,用于保持多人游戏对局在相隔数毫秒的不同机器之间保持一致。它不是单一的系统,而是分为七个部分:

  • 传输:承载数据包的协议,对于实时游戏,几乎总是 UDP。

  • 模拟循环:服务器推进游戏世界的频率,即刻度率。

  • 复制:每个玩家接收到什么数据,以及接收的频率,即更新率。

  • 权限:哪台机器拥有最独裁裁的决定权,通常是权威服务器。

  • 托管模型:该模拟运行的位置。

  • 同步模型:机器之间如何保持一致。

  • 延迟隐藏:客户端预测、插值和延迟补偿。

该技术栈中的任何一个部分都不是完整的解决方案。每个部分只决定某些事情,剩下的则交给其邻近的部分。高刻度率对于问题路由无济于事。预测对于丢包也无能为力。

文章的核心洞察

  • 延迟是有底线的,其他所有因素都会在此基础上累加:两台机器之间的物理传输时间是任何网络游戏所能达到的最小延迟。路由、Tick率(滴答率)、更新率和处理过程都会增加延迟。网络代码(Netcode)无法消除这种延迟,它只能决定玩家在何处感受到它。

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

  • 延迟补偿转移了成本,但并未消除它:延迟补偿会倒回服务器,使高Ping值玩家的射击有效,这意味着目标在到达掩体后仍可能被击中。唯一的真正解决办法是保持较小的Ping值差距,这使得它既是一个网络代码问题,也是一个游戏匹配和服务器部署问题。

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

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

网络代码是如何在不消除延迟的情况下隐藏延迟的?

数据通过铜缆和光纤传输的速度是有限的,因此延迟永远不会低于两台机器之间的传输时间。网络代码(Netcode)无法改变这一点。它所能做的只是选择延迟出现在哪里。

每种隐藏延迟的技术都有其代价:

  • 预测(Prediction)让客户端能够立即对自己的输入做出反应,从而使游戏感觉没有延迟。当服务器与客户端不一致时,客户端会被纠正。

  • 插值(Interpolation)将其他玩家的画面稍稍绘制在过去,从而使他们的移动看起来很平滑。其代价是你看他们会稍微有一点延迟。

  • 延迟补偿(Lag compensation)会将服务器倒回至射击者当时看到的画面,从而使高延迟玩家的射击依然有效。在 2001 年的论文中,时任 Valve 开发人员的 Yahn Bernier 描述了这种副作用:当“一个高延迟玩家向一个低延迟玩家射击并命中时,在低延迟玩家看来,那个高延迟玩家似乎是以某种方式‘绕过拐角射击’的。”

每种技术都是在用一种异常现象去交换另一种。所有这些技术都是在给定的延迟基础之上发挥作用的。

这一延迟不仅由距离决定,而且游戏开发商对其他因素完全无法控制。2015年,拳头游戏(Riot Games)的工程团队解释说,骨干网提供商和 ISP “会优先选择更便宜的路线,而不是更快的路线。”在一条旧金山到波特兰的连接上,“直连可能只需要 14 毫秒,但效率较低的路线则需要整整 70 毫秒。”

距离决定了延迟的下限,而路由决定了你高出这个下限多少。做出路由选择的是 ISP,而不是开发商。开发商真正能选择的是服务器的位置,这决定了根本有哪些路线可供选择。

谁来托管游戏逻辑,它又是如何保持同步的?

这是两个独立的选择,任何同步模型都可以在任何托管模型上运行。

谁托管游戏逻辑(即模拟运行的地方):

  • 点对点 (Peer-to-peer):由一位玩家的机器进行托管。该玩家的网络延迟为零,而其他所有人均依赖于该托管主机的连接。请参阅点对点 (peer-to-peer)。

  • 中继 (Relay):服务器在玩家之间转发数据包。它不运行模拟,也不进行任何验证。请参阅中继服务器 (relay server)。

  • 专用服务器 (Dedicated server):模拟在开发者控制的机器上运行。这消除了托管主机的优势,并为每位玩家提供了一个中立的连接点。其代价是成本和覆盖范围,因为必须为服务器付费,且服务器必须足够靠近每位玩家。请参阅专用服务器 (dedicated server)。

机器之间如何保持一致(同步模型):

  • 帧同步 (Lockstep):机器之间仅交换输入,在所有人的输入到达之前,没有任何人可以行动。输入延迟等于网络延迟,且模拟必须是确定性的。在策略类游戏中很常见。

  • 回滚 (Rollback):每台机器预测其他机器的输入并立即进行模拟。当实际输入与预测不符时,游戏会回退并重新模拟。控制感是即时的,代价是会出现画面修正和额外的 CPU 消耗。格斗游戏中的标准配置。请参阅回滚网络代码 (rollback netcode)。

  • 状态同步 (State replication):服务器发送快照,客户端通过预测、插值和延迟补偿来隐藏延迟。射击游戏的标准配置。请参阅状态同步 (state replication)。

输入延迟和回滚是对同一个问题的两种回答:在另一个玩家的输入仍在传输途中时,玩家的屏幕应该呈现什么?Edgegap 对输入延迟与回滚 (input delay vs rollback)的对比涵盖了各自适用的场景。

托管决定了谁来承受延迟。同步决定了延迟呈现出来的效果。两者都无法决定延迟有多大。

玩家所说的“糟糕的网络代码”(Bad Netcode)是什么意思?

玩家报告的是症状,他们很少会指出具体是哪一层出了问题。同一个投诉可能由多种原因引起,而每种原因都有不同的解决办法。


玩家报告的现象

通常背后的技术层

术语

子弹在目标进入掩体后击中

在高延迟差下工作的延迟补偿

延迟补偿,Ping 值

传送和瞬间回弹

服务器对发生偏差的客户端进行修正

不同步,橡皮筋效果

整场比赛出现卡顿

服务器未能在 Tick 预算内完成计算

Tick 率

角色在移动中途冻结

丢包

丢包

单次击中造成的伤害超过了单颗子弹应有的伤害

多次射击在同一次更新中到达

更新率

最后一行就是 Battle(non)sense 在其 2017 年的“Netcode 101”视频中描述的“超级子弹”(super bullet)。在每秒更新 10 次的情况下,一把每分钟射击 750 发或更快的枪会将两颗或更多子弹放入单次更新中。

第一行归结为延迟,以及延迟在比赛玩家之间的分布是多么不均匀。没有任何网络代码技术可以控制这一点。服务器部署位置是开发者掌握的主要杠杆。

Edgegap 测试了最有利于直接连接的情况。在 2020 年对一款 1v1 主机游戏的 122,000 场对等网络(P2P)比赛进行的分析中,将每场比赛通过部署在两名玩家之间最佳可用位置的服务器进行路由,在 70% 的比赛中使平均往返时间降低了 23%(1v1 案例研究)。在其余 30% 的比赛中,它并不比直接连接快。Edgegap 的网络代码基础文章涵盖了完整的论证过程。

来自我们的赞助商(其实就是我们自己!)的寄语

大多数延迟来自距离,而非代码。Edgegap 的边缘云是一个分布式网络,按需提供高达 615+ 个可用位置,因此每场比赛都能在最适合玩家的可用位置运行。对直播工作室流量的独立重放测试表明,与公共云相比,平均往返时间减少了 58%。

您的引擎网络代码适用于何处?

引擎的网络层是开发人员进行构建所基于的接口:Unity 的 Netcode for GameObjects、Mirror、Fish-Net、Unreal 的内置网络、Godot 的多人游戏 API。每一个都实现了堆栈的一部分,例如传输、复制状态的方法,以及在某些情况下的预测。

它们均无法决定权威模拟在何处运行,或者该模拟与每个玩家的接近程度。这两项选择存在于库之上,并且它们设定了库随后必须隐藏的延迟。

Edgegap 的观点(仅代表个人意见,姑且听之即可!)

网络代码隐藏了延迟。而部署位置决定了有多少延迟需要被隐藏。

当测试人员说网络代码很糟糕时,最容易让人想到的做法就是去打开预测代码。但在此之前,请先按顺序检查这四件事:该场比赛中玩家之间的 Ping 值差距、他们连接的丢包率、服务器在负载下是否保持了其 Tick 预算,以及同步失败日志(desync logs)里记录了什么。

只有最后一项检查才完全指向你编写的代码。前三项则关系到延迟有多大以及延迟在玩家之间的分布是否均匀。网络代码可以隐藏延迟,但它无法决定有多少延迟需要被隐藏。

针对长路由去调整预测只能治标。通常,根本原因在于服务器托管的位置。在距离比赛玩家较近的地方启动专用服务器,并保障网络有足够多的节点可供选择,这样才能缩短延迟本身。而网络代码是无法做到这一点的。

-

-

-

雅库布·莫蒂尔

雅库布·莫蒂尔

雅库布·莫蒂尔

,

产品总监

产品总监

产品总监

常见问题

Unity 的 Netcode for GameObjects 与 netcode 是一回事吗?

Netcode for GameObjects 和 Netcode for Entities 之间有什么区别?

我应该使用哪个 Unity 网络代码库:Netcode for GameObjects、Mirror 还是 Fish-Net?

谁发明了回滚型网络代码?

Godot 是否内置了网络代码?

Get your Game Online Easily & in Minutes

立即开始集成!

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