星期五的事实#364 – 1.1稳定

2021-01-29 20:49:35

当我们发布1.0 FFF-360时,实际上是说论坛上有大约150个错误,还有大约80个要解决的内部任务。这些显然是次要问题,难以重现的问题或非常罕见的问题。换句话说,它相当稳定,在谈到Factorio稳定版本时通常不用说。但这被证明是一种错误的措辞,因为一些媒体对此予以了表述,并把它表示为“有错误的发行版”。

因此,我很高兴最终到达这一点,我们在论坛上实际上有0个已知问题和0个活动的错误报告。这就像正确清洁厨房一样,因此您可以开始烹饪新鲜的东西。关于下周的更多信息!

现在,如果您坚持使用稳定的1.0,我们想复习一下您可能会错过的1.1的某些功能。

多年来,人们对此提出了很多要求,我们一直拒绝。原因是,并非所有事物都能翻转,例如油配方,铁路信号,泵站等。由于这些不对称性,如果翻转这些实体的设计图,结果在最佳情况下将无法正常工作并导致故障。在别人的混乱。

但是后来kovarex玩了,真的很想复制并翻转他的火车卸载设置(仅是典型的插入器,箱子和皮带)。因此,他决定只添加它,并通过不允许翻转不会正确翻转的蓝图来避免翻转问题。

我们在最后一刻增加了一些功能,以便在Spiders 1.1中具有功能。这是我们在FFF-362中演示的内容的补充。

试图用蜘蛛浏览我们相当潮湿的游戏测试地图实在令人沮丧。他们总是会被某个湖边困住。排队移动命令似乎是一个很明显的解决方法,最后并没有太多工作。

另一个挫败感是试图在战斗中控制多只蜘蛛。遥控器对于少数蜘蛛工作正常,但是一旦您达到两位数,管理蜘蛛遥控器和蜘蛛就很麻烦了。

因此,除了航路点外,kovarex还添加了让蜘蛛跟随实体...甚至其他蜘蛛...的功能。

在1.1.0中添加了带锁的安全带建筑后,在构建建筑时会发生一些与旋转安全带有关的不明/不确定行为。

因此,我们通过使用新的' Smart Belt building'扩展了皮带构建的功能集来修复了该错误。

有了出色的功能,我们就有机会进行小小的功能爬行。因此,我们增加了自动穿越地下带的抗挫折功能。

在不断进行优化以让玩家建立更大的基础方面,我们经常进行一些小的更改,以使性能提高1-2%。最近,我开始研究对传输带逻辑进行多线程处理的可能性。这是更重要的性能消耗之一,并且仍在单线程中完成,从而带来了巨大的潜在性能提升。

运输带已经进行了非常优化(FFF-176)。可以简单地说"使其成为多线程"但是要想在多人游戏中运行时不会引起任何问题,甚至还需要解决许多技术难题。基本上,确保它仍然是确定性的。

尝试在同时更新所有传输线的情况下执行朴素的多线程操作是行不通的。在图1中:根据首先更新哪条运输线,铜板可以在铁板之前或之后着陆。可以通过使用各种同步原语来解决此问题,但是使用它们会增加代码的复杂性,以至于没人愿意维护它,并且主要是不能保证代码会更快或不会取消同步。

经过一些观察,我注意到了一个琐碎的事实:并非所有传输线都可以相互影响。

在图2中,水平皮带的左输送线永远不会从水平皮带的右线接收任何物品,也不会接收任何来自侧面装载的物品。这给了我一个简单的好主意。我们可以以某种方式对传输线进行分组,即一组中的线不会与任何其他组中的任何线交互。这意味着,我们可以避免传输线之间的所有同步逻辑。当一个线程更新一组时,其他线程可以同时独立地更新其他组。

每种颜色都是不同的传输线组。每个组并行更新。

维持这些组本身是一个挑战:当玩家建造或旋转运输带,地下带或分割器时,运输线将改变它们的连接,并且某些组现在可能已连接,并且需要合并。反之亦然:播放器能够删除一些连接,从而使该组包含可以提取到单独组中的多个组件。尽管必须立即进行组合并(使多个组能够相互交互会产生竞争条件),但拆分并不需要。

到目前为止,我们面临的最大问题是运输线不是完全独立的。从0.9版本开始,我们就在游戏中提供了一种睡眠/唤醒机制,它的样子是这样的:当两条传输线上都没有任何东西可以保存UPS时,从传送带上取走的插入器可能变得不活动。如果没有任何方法可以将不活动的插入器卡在该位置上。在这种情况下,插入器会在传输线上进行注册,以便在有新物品进入时可以将其唤醒以检查是否需要拾取任何物品。

由于通过一条传送带的两条传输线可以属于不同的组,所以这些组不是独立的,因为它们都可能试图唤醒/使同一个插入器进入睡眠状态。在这种情况下,插入程序将成为两个组的共享状态,必须正确处理。传输线不能简单地唤醒该插入器,因为它可能被另一个线程唤醒,并且激活顺序很重要,因为它还定义了更新插入器的顺序。如果插入器将以其他顺序激活,则会发生不同步。

为了解决这个问题,线程在工作时不会立即唤醒实体,而是将唤醒请求添加到列表中以供以后处理。完成所有线程后,主线程将收集并合并所有这些请求,并根据组更新顺序号以确定的方式唤醒实体。

在唤醒列表和其他类似情况得到正确处理的情况下,我开始比较一些基于皮带的巨型数据库,这些巨型数据库每分钟可产生10k科学数据,我注意到传送带更新时间从4ms降低到1.6ms,总更新时间为20至整体性能提升40%。

原始的Trains GUI在0.13中添加,并且仅在外观上一直进行了更改,直到1.1.0。

当时这是向前迈出的一大步,因为没有其他与火车互动的好方法。例如,您无法从地图视图中打开它们,甚至无法缩放到世界,并且机车GUI非常有限。

在过去,人们的心态是,在极端情况下,玩家只有几列火车或最多10-20列火车,因此我们并没有真正需要对其进行大量分类。

随着时间的流逝,游戏不断发展,工厂不断壮大,随后火车的数量不断增加。在我们内部的1.1游戏测试中,GUI的不足之处变得非常明显。我们玩了整整一个星期,并广泛使用了新的火车限制。我们有超过100列火车和200多个车站。

完成后,我问了团队的其他成员"有人甚至没有打开过Trains GUI吗?"。答案是"否"。

在进行游戏测试时,我也非常熟悉我希望Trains GUI具有的功能以及它应该回答的问题:

我首先在Lua中制作了一个模型Mod。它使我能够以比C ++更快的速度快速迭代GUI上的设计和内容。 2天后,我基本上完成了最终设计。在审查了模型之后,我们同意这是一个巨大的改进,并决定适当地进行。我把它当作'圣诞节作业'用C ++将新的Train GUI编写到引擎中(即使编程不是我的专长)。新年过后,它已经准备好了,所以我们进行了常规的质量检查,并在1.1.8中发布了它。

新的Trains GUI有两个选项卡,每个选项卡都遵循一个简单但有意义的设计原则: ...从老实说,一切都落到了位。但让我解释一些细节...

我要说的是,最有争议的部分是删除每张火车地图下的“时刻表”显示,并用“状态描述”按钮替换。时间表显示在侧面,几乎完全是冗余信息。状态按钮提供了更为精确和相关的信息,您可以看到它要去的停靠站,距离有多远,还可以单击状态按钮以在要去的特定火车停靠处打开地图。

令人高兴的是,只要您的日程安排有误或不一致,您都可以在此列表中轻松注意到它。

由于“电台”选项卡是全新的,因此没有任何变化是人们可以不同意的。使用此选项卡的目的是尝试以某种易于理解的方式呈现有关每个车站的火车限制的信息。

以<预订> /<火车限制>形式的注释被保留。描述工作站状态。 当我查看单个产品的Dropoff + Pickup站时,我可以轻松识别3种基本状态: 火车数量不足:< Reservations>之和与< Train limit>之和相比太低。

输入的信息不足:几乎所有的火车都在接机中等待装载。

备份:<预订> =<火车限制>在下车的地方,火车正在等待被卸载。

多年来,Factorio我进行了很多优化。运行时性能,启动时间,保存,加载,甚至退出速度。在不更改游戏功能的情况下,找到任何需要改进的地方变得越来越困难–我主要试图避免这种情况。自动保存时间一直是其中的一个"我希望它可以更快一些"但从来没有发现任何突出或可以衡量的改进。

几年前,我并行执行了迭代游戏和压缩并保存到磁盘(FFF-201)的操作,但是此后没有任何重大改进。我总是会遇到的问题是:我可以使这两个过程之一更快,但另一个总是瓶颈,因此总体速度不会改变。每隔几个月,我都会重新讨论它,并尝试思考使之更快的新方法,但总是遇到相同的问题。

前一周我又做了一次,我想知道如果我能“假装”那么保存过程会快多少呢?压缩和写入磁盘没有发生。结果是;很多。保存量越大,等待压缩并写入磁盘的时间就越多。经过一会儿的思考,我决定将地图信息分成多个压缩文件,而不是将地图信息保存在一个大的压缩文件中。这不是一个新概念,但我们以前在Factorio中并未做到这一点。经过30分钟的快速实施,结果表明,无需进行太多更改-即可正常工作。

最终结果意味着压缩和写入磁盘并行处理从未阻塞主要的迭代游戏逻辑。仅此一项就使整个保存过程加快了约20%,结果是我对主逻辑所做的任何改进都直接带来了进一步的改进。在测试中,我执行了较大的节省操作,从而节省了2倍以上的时间。

感谢您的收看,让我们知道您在平时的想法。