17173 > 游戏资讯 > 官方公告 > 正文

《人工智能战争2》版本更新 - 5.808 - 内存性能深度优化

2026-05-24 04:50:41 神评论
17173 新闻导语

《人工智能战争2》5.808版本重磅更新!深度内存性能优化,大幅减少GC抖动,游戏运行更流畅。Armada与Dyson阵营平衡性调整,全新钻头系统让资源管理更具策略性。查看完整更新日志!

完整发布说明。

我已经有一阵子没有深入参与这款游戏的代码工作了,但现在我又回来了。这次的代码更新规模相当大,并结合了《Heart of the Machine》的一些类似更新。我想着干脆同时处理这两款游戏——《AI War 2》从中获得的收益甚至比《Heart of the Machine》还要大!

关于Badger在模组方面的工作,对Armada Empire阵营进行了一系列调整,包括平衡性和经济系统的全面重构。对于Dyson Empire,主要是平衡性改动;虽然有一些削弱,但主要是为了让Reapers(Dyson的敌人)在高难度下更具威胁。

5.808 内存地狱 更新日志
常规
  • Imperial Spire:AI King在Dire Guard Posts被摧毁前将无法被锁定。这将使Imperial Spire在终结游戏时效率略有提升。
代码优化
  • 游戏现在设定使用C# 13语言标准,尽管仍运行在.net 4.7.1上。这一点很重要,因为我需要用到C# 8和10中的一些特性,且Unity也提供了支持。不过,由于它包含的内容超出了游戏自身运行所需,所以不要使用那些特性(虽然编译能通过,但游戏会卡死,所以不用担心)。
  • FunctorComparer现在改为结构体(struct),因此在对列表等进行排序时不再产生内存分配。
  • 更新了所有的排序操作,使其现在变为静态排序。这涵盖了主游戏以及所有未损坏的模组。这大幅降低了这些操作带来的内存压力。
  • 向后移植了《Heart of the Machine》的线程控制改进,使得长时间运行的线程能更快启动并更高效地复用。这也使得ThreadStatic的命中更加一致。
  • 修复了大多数集合的枚举器获取方式,使其不再导致装箱(boxing),从而减少了垃圾回收(GC)抖动。
  • 修复了小型结构体以正确使用IEquatable,这样当它们作为字典的键或值时,不再会被装箱,从而进一步减少了GC抖动。
  • 修复了最初确定的19个导致ForEach/DoForEach产生内存问题的点中的18个。随后又发现了另外2800个使用相同模式的地方,由于对代码库的改动影响太大,暂时未对其进行修改。
  • 修复了ArcenInput中一个非常愚蠢的错误:当文本框存在时,它会在每帧多次调用以检查文本框。这在屏幕上有文本框时增加了延迟和内存压力。
  • 移植了《Heart of the Machine》中ArcenDoubleCharacterBuffer的一些改进,但只移植了少量以避免破坏模组。现在的情况是,在无操作(no-op)情况下内存压力更小。
  • 改进了EnumIndexedArray类家族的处理方式,使其不再装箱,从而不再增加内存压力。我们在之前的7.3版本语言中无法做到这一点,但现在成为可能。它遍布整个代码库,每次调用都能节省17字节。每帧有数百次调用,因此可以节省数KB。这是在每帧测量到900KB消耗的情况下实现的,即便是在之前的优化被验证有效之后。
  • 现在,当需要时,我们从Cloudflare运营的另一个服务获取IP地址。它响应迅速,没有我们过去使用的服务有时会出现的延迟和中断问题。
  • 为游戏使用的许多代码类型提供了一种新型的、无闭包、基于结构体的可枚举表面(enumerable surface),这些可以在不产生垃圾的情况下进行迭代,形式为 foreach ( var v in theThing) {},而不是像过去那样使用 theThing.DoForEach( delegate (var v ) {} );。代码非常相似,但不会产生垃圾,而旧代码总计每帧产生数百KB的垃圾。不过,有超过2600个调用点,且存在模组,因此旧样式和新样式将共存,并会在有时间时逐步转换。其最终结果是游戏运行更快、更准确,因为它们不需要通过堆来获取迭代所需的数据。这主要有利于模拟速度而非帧率,且对更大、更复杂的游戏受益最大。
  • 更新了ConcurrentDictionary以使用一种新的枚举器样式,该样式零GC、不涉及yield、结果与之前相同,在有条目时比之前快1.9倍,在字典为空时比之前快4倍。这种情况随处可见,因此这是一个重大改进。
  • 线程中止异常(Thread Abort Exceptions)现在被刻意静默,因为它们是游戏正常运行的一部分,玩家无需担心。此外,许多位置已调整为使用这些异常。
  • 大量代码已转换为使用新的foreach样式,而不是闭包样式。它在功能上完全相同,但不会在堆内存中产生垃圾。我已经对模组和外部代码进行了一次大规模的清理。
  • 我们多年来使用的自定义StringBuilder类缺乏官方版本具备的多种硬件加速功能。它已被弃用。
  • 增加了一个新的ChainList,由BucketedArrayPool支持。这用于GameCommands,以便它们可以“软复用”内存,进行借出和归还。这比我多年来在《AI War 2》中使用并在《Heart of the Machine》中进一步完善的循环数组池概念稍微复杂一些,但大体思路是一样的。基本上,有一个库,ChainLists向库请求租用特定大小的数组(目前int、float、string和FInt为16和32个条目,但可以是任何大小),然后它们会保留一定数量的已归还但未超过特定大小的租用数组。16和32的大小比GameCommands过去使用的4和8大得多,这实际上会使它们在必须扩展之前有更多的余量,并应有助于平衡锁定访问库与直接分配的性能。对于较小的列表,这确实会导致很多“浪费”的内存,但这并不是问题,因为它们在最慢几秒内(通常更快)就会被回收。尽管有这些额外的余量,但这种方法所需的总内存池实际上更少,因为我们不涉及GC。目前,它只允许为其目标站点使用约32MB的内存。这应该涵盖了拥有大量AI的繁忙多人游戏所需容量的两倍左右。如果游戏总计仍需要更多内存,那么它将像现在一样继续向堆分配。作为整个契约的一部分,枚举非常快,但直接索引list[int]是不允许的,因为这非常慢且毫无意义。其内部结构是数组的链表,这类似于微软ConcurrentQueue的结构方式,出于同样的原因,它也没有索引器。另一方面,ChainList假设同一时间只有一个线程在写入,但任意数量的线程在读取,这与我自定义的List<>方法一致。这规避了ConcurrentQueue的一些最严重的缺点,当然代价是ConcurrentQueue可以同时有多个写入者,而ChainList则不能。
  • 游戏现在已完全转换为所有GameCommands使用ChainList,所有模组也已更新以使用它。每帧峰值GC调用已从900kb下降到416kb,老实说,节省的幅度比预期的要小,但这只是意味着某些东西仍然以某种方式在进行装箱。其他较小的帧每帧都下降了50-100kb,除了那些已经处于约50kb的最小分配帧之外。这在GC抖动方面节省巨大,应该会让游戏整体运行更流畅。不过,我还会继续深入调查。
  • 增加了一个新的小型Python程序,用于重新编译所有模组,这在这里比我在《Heart of the Machine》中的版本更有用。它还会跳过任何明确被禁用为不可用的模组,这很不错。
  • 修复了调试路径中的一些问题,该路径在网络/序列化代码中使用了闭包,触及了C#编译为IL的一个怪癖。基本上,当多个闭包引用同一个东西时,会导致它们被装箱。这导致了巨大的GC抖动——即使在日志关闭的情况下,甚至在单人游戏中,每网络帧至少200kb。这是一种巨大的浪费,现已重构为不使用闭包,以避免触发此Bug。
  • 修复了另外55个左右与各种集合中的值类型相关的装箱点。这在我的移植清单中,但之前还没来得及做。
  • 系统菜单的“关于”部分设置为拥有可展开的区域,这些区域在菜单中不再导致巨大的GC分配(之前仅那个窗口打开时,每秒3次,每次产生2.8MB的GC)。
  • Escape菜单现在显示内存、帧率和模拟速度,全部合并在两行内,比以前清晰得多。该菜单中其余的扩展详细信息现在位于可展开的子部分中,正如在《Heart of the Machine》中那样。这防止了Escape菜单本身每秒3次冲击GC。有了这个,我可以轻松验证每秒增加的GC压力在1-5MB之间,而不是像以前版本那样超过50MB。
  • 修复了一个问题,即在过去的某个时间点,工具提示被设置为具有不受限制的更新速度,且没有正确缓存其最后的值。这导致工具提示在视觉上没有区别,但导致它们使用了更多的CPU,并每帧产生约200-400kb的内存压力。现在这种情况不再发生了。
  • 修复了右上角持续显示的消息显示的问题,它之前每帧都在重新计算文本大小,而不是在文本更改时计算,这导致它大量占用CPU和内存。
Forge of Empires
    [h4] Armada [/h4]
    • Tyderian Abomination现在为Armada提供更多资源
    • 削弱Jrathek,使其不再能瘫痪Elderlings
    • 增加了一些Tyderian舰船的质量;进一步削弱Jrathek
    • 改进了Tyderian召唤黑客的描述,以标明涉及的资源
    • Korlarh不再能被僵尸化,科学矿井的金属成本增加(固定200K)
    • Armada矿井不再使用“挖掘次数越多资源越少”的概念;取而代之的是钻头分级:每挖掘X次,就需要使用更高级别的钻头;这会产生更多资源,但成本更高。旨在让金属成为更重要的约束条件,这样你就不能以最小的努力无休止地挖掘科学,并让事情变得更有趣。理想情况下,这会让玩家感到他们需要更多的金属,从而去占领生产建筑。
    [h4] Dyson Empire [/h4]
    • 让Reapers真正遵循其难度设置;之前它们的许多难度调整仅在“难度5”生效;更高的难度级别现在应该更有意义了。特别是,在高难度下挖掘行星会有更高的AIP成本。
    • Spheres不再能彼此相邻建造
    • Neinzul Moon无人机现在更容易损耗
    • 非常感谢The Grand Mugwump提供的详细笔记和建议,也感谢Ktosiek提供的额外反馈。
    • 对DZ Empire的Zenith和Templar炮塔进行了一些削弱。

    《Heart of the Machine》1.0现已发布!


    【来源:steam】
    我想了解这个游戏:
    官网 专区 下载 礼包
    关于人工智能战争2的新闻
    17173 首页全新改版规划中!现向各位玩家征集真实使用意见,你的想法将直接影响新版页面设计~动动手指填写问卷,快来共创你心仪的页面布局吧! 参与问卷