Alt-F4 #41 - 标题载入中,请稍后…  2021-07-09

作者 oof2win2, 编辑 stringweasel, Nanogamer7, Conor_, Therenas, Firerazer,
翻译 Ph.X

目录

在本周的第 41 期中,oof2win2 带回了一篇有点技术性的文章,讲述在试图连接到多人游戏时到底会出什么问题以及如何解决这些潜在问题。如果你曾经想知道为什么异星工厂不让你加入你朋友的多人游戏,这篇文章可能会给你一些解释!

快速性能检测 oof2win2

玩家从游戏中掉线的图像

如果你没有一台顶配电脑,那么就很可能曾看到这样的提示,告诉你因网速或电脑跟不上而被从游戏中踢出。那么,这实际上意味着什么?从短期和长期来看,你能做些什么来改善这一状况?

网速问题

有时,你的网络也会出问题。这可能是由于许多原因,如你的 ISP 正在维护或你的 DNS 数据中心遭遇停电。不过你可以用一些实用工具来缓解此类问题。

然而,要解释异星工厂网络的工作原理,将是个漫长的篇幅。cubeFFF#136 中很好地解释了这个过程。他们所做的最重要的事情之一是使用 UDP,但把 TCP 中的功能加了回去。UDP 的优势是比传统的 TCP(用于大多数日常事务)要快得多。UDP 通过去掉“握手”来实现这一速度,“握手”是指两个客户端(计算机)同意他们要通信并建立一个连接,这意味着它不关心数据会发生什么,只管发送。然而,这也消除了保证数据交付的能力,正确排序数据或删除重复数据(有时会发生这种状况)。

UDP 缺乏可靠的数据传送直接违背了异星工厂必须使用完全确定的锁步算法工作方式,正如我在先前文章中解释的那样,数据必须送达,否则你会收到一个解同步。cube 说 Wube 已经解决了这个问题,他们在 UDP 中实现了 TCP 协议的一部分。这意味着他们既获得了想要的速度,也拥有了 TCP 的可靠性——至少接近,毕竟异星工厂协议没有公开以供分析。不过 Hornwitser 已经用他的剖析器分析了流量,这甚至帮助修复了一个从 0.17 开始就存在于游戏中的 Bug!

UDP 也非常重要,因为它允许 NAT 打洞。NAT 打洞是你的客户端请求外部服务器(PingPong 服务器,这是一个由异星工厂托管的专用服务器)告诉异星工厂服务器来与你的客户端建立连接的过程,因为一些路由器和防火墙可能会阻止来自你没有请求过的 IP 的“随机”连接,这对防止别人对你的电脑进行暴力攻击很有好处,但对异星工厂开发者来说则是一个障碍。

NAT 打洞示意图

现在,让我们试试解决你从异星工厂中掉线的问题。首先,你可以使用 Ookla 测速fast.com (Netflix) 等网站进行网速测试,检查你的网络是否足够快。这两个网站将测量相似的数据,供你自由选择。然而,有三个数据很重要(参考 Ookla 测速):下载速度、上传速度和延迟。

Speedtest.net 结果以供参考

对异星工厂而言,你的下载和上传速度不需要很高,因为地图(存档文件)是在你连接到服务器时发送过来的。地图的下载速度取决于你的下载速度和服务器的上传速度;你的下载速度不可能超过它的上传速度。一般来说,存档文件在 50MB 以内(前提是你没装过大量 Mod),所以在平均连接上,一个存档文件能在 15 秒内下载完成。不过存档文件的下载速度并不重要,因为它最终只是一个文件传输。然而,你的下载速度确实会影响到你要追赶多少 Ticks(在你下载完成后加载地图的部分)。总的,这一步 应该 没问题,虽然耗时可能不同。

“追赶”是异星工厂一个非常特殊的过程。它意味着你正在赶上游戏中的新动作,因为你有一个旧的副本,服务器不能瞬时给你发送一个全新的存档副本供你运行。事实上,加入多人游戏会话的过程看起来像这样:

  1. 服务器在一个特定的 tick 保存地图,比方说 tick 100,并将保存的地图发送给你。服务器从现在起也开始向你发送所有的变化(仅用户输入,正如我队异星工厂多人游戏本身的另一篇文章中所述)。
  2. 你下载地图。然而,你没有一个优秀的宽带,所以下载需要 90 tick,在此期间,有其他玩家在游戏中游玩并创建了其他东西。
  3. 由于你比地图的当前状态晚了 90 tick,你不能加入游戏。但是服务器已经把玩家做的每一个动作都发给你了,所以你的客户端开始模拟游戏,并在正确的时间点加入动作。当游戏被模拟到与服务器的副本处于相同的 tick 时,你终于加入游戏了。

然而,在第 3 步可能会出现问题。有时,“追赶”的进度条不会移动,而是停留在原地。这个问题是由于你在模拟游戏时的速度与服务器的运行速度相同,所以你永远无法赶上那 90 个 tick。一个比喻是,如果你以 6km/h 的速度在轨道上跑步,但轨道每小时会延长 6km,那么你永远无法抵达轨道的终点,因为你会以轨道建造时的相同速度运行。需要说明的是,追赶与网络无关,而是与潜在的硬件瓶颈有关,我将在后面解释

Ookla 测速的另一个参数是你到他们的数据中心的 Ping(延迟)。但这对于异星工厂服务器来说并不总是准确的,因为异星工厂的服务器可以在世界任何地方,而 Ookla 将你连接到你 最近 的数据中心。

可靠性

你的网速和延迟是一回事。然而,网络的可靠性要重要得多。网络可靠性差的一个比喻是,如果有人向你发送了 100 条信息,但只有 10 条真正送到你手中(在网络术语中,这将被视为 90% 的丢包)。网络可靠性的差异很大,比如有一天,你的数据包可能在正常传输,而另一天,可能会有鲨鱼吃掉你的数据。网络可靠性可以在命令行里 ping 命令来测量,或者使用诸如 StarTrinity’s Constant Speed Test 这样的软件来测量,它更方便用户使用,并能显示一些额外数据。例如在下面的图片中,你可以看到下载多次失败,这是由于不可靠的网络连接造成的(关掉网络连接可以模拟这种情况)。在现实中,你的结果可能不一样。无论如何,StarTrinity 测速也是找到 WiFi 信号最佳点的一个好方法。

StarTrinity 结果以供参考

解决不可靠的互联网连接的方法是使用有线以太网而非无线连接。有线连接更可靠,因为数据是以电的形式在(通常是)铜线上传输,但无线可能被混凝土墙或墙内的金属加固物阻挡。如果你真的必须使用无线,你至少应该考虑从 5G 切换到 2.4G,因为 5G 的范围更短,比 2.4G 更容易被电波路径上的物体阻挡。

硬件瓶颈

到目前为止,我把重点放在错误信息的“网络”部分。上述信息的另一部分是“或计算机”。这意味着,也可能是你的硬件阻碍了游戏的顺利运行。你可以启用各种调试设置来检查这一点,例如 show-fps 调试选项,显示你的 FPS 和 UPS(FPS是每秒帧数(图像),UPS 是每秒更新数——游戏更新的速度,由你的 CPU 决定)。要启用一个调试设置,你要按 F4 -> 勾选你所需的 -> 再按 F4 来隐藏菜单。该设置将从那时起一直保持启用直到你禁用它。

一个非常重要的设置是 show-time-usage,可以看到哪些东西占用了你的 CPU(UPS)时间。这将显示游戏中正在计算的东西的列表,包括实体路径、流体计算、电力网络和机器人寻路。如果游戏要顺利运行,你希望总和都低于 16.66ms(1/60秒)。如果有什么东西占用了大量时间,你需要考虑一下:如果是机器人而且你有 50000 个机器人在某个地方飞来飞去,试着禁用你工厂的那一部分,看看之后的时间使用情况如何。

你可能会想“为什么服务器不为我计算这些内容?”嗯,这主要是因为比起每次都发送所有的数据,只发送数据中的新增部分(就像我在多人游戏文章中所描述的那样)要容易得多。在异星工厂中,客户端运行 与服务器相同的模拟,所以你的 CPU 需要能运行与其他人 CPU 相同的计算。

该怎么办?

你可以尝试改善你的工厂的性能,比如把所有的电力生产转为太阳能。但靠改变工厂本身能做的优化很有限。因此,这里列出了一些对不可控事物的补救措施,例如污染。

解决朋友无法追赶最简单的办法是暂停游戏。这可以通过按 shift+space 来实现。但这只是暂时的方案,因为在你取消暂停游戏后,游戏仍然会模拟,所以你朋友的电脑可能还是无法跟上。

如果你有很多污染的地方,而且你在游戏后期,虫群只是一个扩张时的小麻烦,你可以运行这个命令:

/c for _, surface in pairs(game.surfaces) do
  surface.clear_pollution()
end
game.map_settings.pollution.enabled = false

它将清除游戏内每一个表面的所有污染,并禁用污染的产生。这在某些情况下可以提高相当多的性能,因为它将不必再模拟污染。

如果你认为污染不适合你,并且有大量的虫巢在挂机,你可以运行这个命令:

/c game.forces["enemy"].kill_all_units()

它将杀死 "enemy" 阵营中的所有虫子(不做修改前的话)。然而,它 只删除移动单位,如撕咬虫和喷吐虫,而不是虫巢或沙虫。如果你也想移除这些,可以用这个命令来代替:

/c local surface=game.player.surface
for key, entity in pairs(surface.find_entities_filtered({force="enemy"})) do
  entity.destroy()
end

如果你 还是 觉得虫群很烦人,而你的基地能在无需任何投入的情况下直接处理它们,你可以用这个命令代替:

/c local surface = game.player.surface
local mgs = surface.map_gen_settings
mgs.autoplace_controls["enemy-base"].size = "none"
surface.map_gen_settings = mgs

它将禁止虫群在你的表面产生,默认是 Nauvis,不过它不会影响现存的虫群(你将需要使用前面的命令)。

如果这些方案都不起作用,最简单的办法是降低游戏速度。一切都会运行得更慢,但你将能够与你的朋友一起玩,而不会被踢出:

/c game.speed = 0.8

这个命令通过改变游戏的速度(从而降低 UPS)来减慢游戏的速度。默认值是 1,但你可以低至 0.01,这时几乎什么都不会动。最好的办法是从 1 开始以 0.1 或 0.05 的阶梯下降,比如 0.9、0.8、0.7 等等。这个命令将在全局范围内降低游戏的速度,所以每秒钟要计算的更新会更少。你屏幕角落里的 UPS 数字将是基础值乘以这个常数:$ 1 \cdot 60 = 60 $, $ 0.8 \cdot 60 = 48 $, $ 0.5 \cdot 60 = 30 $。

如果你想看到更多的 Lua 魔法,所有这些都来自控制台 wiki 页面。要运行任何命令,只需复制并粘贴进你的聊天栏发送。

通过设计优化

你可能也注意到了,我没有提到你的 GPU 可能会拖后腿的问题,尽管顶部的信息说“你的电脑”。原因是异星工厂并不关心你的 GPU 是块 3090 Ti 还是集显,它只会让它“渲染东西”。如果它来不及渲染,那也没关系。你总是可以降低你的分辨率或调调异星工厂的图形设置来改善下。

异星工厂在设计上就一直在做优化。Therenas 在他的帖子中剖析了 1.1 的性能升级,异星工厂开发者还有很多与优化游戏有关的帖子(所有的 FFF 都由 spielsw 整齐地分类归档,你可以很容易地找到优化相关的文章)。

征稿

一如既往的,我们正在召集任何想要为 Alt-F4 做出贡献的人,无论是提交文章还是帮助翻译都可以。如果您有些有趣的想法,并乐于与社区分享,这里就是一个好地方。如果您没有太大把握,我们会很乐意帮助您讨论内容创意和结构问题。如果您有意参与,从加入 Discord 开始吧!