作者shirman (跟风向对干克什米尔居民s)
看板Paradox
标题[CK3 ] 开发日志#187(普天之下) 效能与优化
时间Wed Oct 15 22:35:53 2025
译注在前:
挖塞,整个欧亚大陆都要纳进来,我的电脑一定跑不动啦
你也跟我有一样想法吗?
今天官方就要对这个议题来场直球对决,我们来看看他们怎麽说吧
正文开始:
我是 Joel,《十字军之王 III》团队的技术主管。
这是我投入《十字军之王》系列开发的第二个十年——我最初是以《CK2》的游戏设计师身份加入的。
在深入探讨我们如何提升模拟效能之前,先交给 Daan 来为各位做个简短的成果总结。
开门见山的摘要
想直接知道重点与结论?那我就简单为你总结一下!
随着《普天之下》(All Under Heaven)的加入,游戏的「可游玩范围」扩大了约 30% 至 40%,包括可控制的土地与在世角色数量的增加。
我们的重点是缩短模拟运算时间(tick duration),以确保整体游戏体验与目前版本的《CK3》同样流畅。
根据在高配与低配电脑上的测试结果,我们成功让模拟速度与现行正式版相当。
所谓「相当」的意思是:
在游戏初期稍慢一些,但在中後期(模拟 150 至 250 年、以 1066 年开局、速度5运行)则与现版持平或略快。
以下的图表显示了在 150 年模拟过程中,各版本的每次运算时间变化(数值越高代表运算时间越长、速度越慢):
http://i.imgur.com/48SZfSJ.jpg
图注:模拟运算时间概略图——红线:〈普天之下〉版本,黄线:现行版本
我们同时也对 介面(GUI)、3D 图像与记忆体使用量进行了优化,不过这些项目在优先顺序上仍低於「模拟速度」的改善。
需要注意的一点:
实际效能仍会依据玩家所创造的世界、以及游戏模拟过程中生成的世界状态而有所差异!
没有任何一个数值或图表能涵盖所有电脑配置与游玩风格,但我们的目标是让《普天之下》在任何情况下都能维持流畅、稳定、可玩的体验。
以上就是简短版。若你想了解更深入的细节、更多图表与分析,就请继续往下看吧!
定义
让我们回到正题,开始深入细节之前,先明确定义我们所说的「速度」与「效能」究竟是什麽。
一般而言,我们会将效能分为两个主要面向:
1.绘图效能(Rendering)
2.模拟效能(Simulation)
在开发大型战略游戏的资料片时,游戏内需要模拟的系统与物件会不断增加;
虽然画面复杂度也会提升,但在这类开发中,绘图通常不会成为新的瓶颈。
然而,模拟负担的增加意味着 CPU 必须进行更多计算与资料转换,这使得CPU 几乎成为模拟效能的最大瓶颈。
因此,我们在优化程式时,最常做的工作就是检视 CPU 周期的耗用位置,找出可提升效率的地方,以降低每个「模拟刻(tick)」所需的平均时间。
因此,「单次模拟运算时间(time-per-tick)」是我们在开发过程中最重要的追踪指标,也将是本篇开发日志的重点之一。
(译注:名词解释
1. 模拟刻(tick):游戏模拟世界更新一次的最小时间单位。
在CK3中,每个 模拟刻 就是游戏世界的1天。
在同一天内,AI 思考行动、事件发生、角色关系更新、经济与战争计算都会执行一次。
2.单次模拟运算时间(time-per-tick):
这是指电脑实际花多少「真实时间」去计算一次 模拟刻 的内容。
假设你的电脑跑1天要0.1秒,程式优化後,跑一天只要0.05秒,就代表效能提升了一倍 )
效能测量
那麽,该如何在如此复杂的模拟环境中准确测量 模拟刻(tick)速度呢?
实际上,有许多变数会影响最终结果,例如:
*图形设定
*硬体效能
*测试时长
*游戏所处的早期或晚期阶段
*背景程式占用
*随机变化
这些因素都会影响效能分析,但我们要强调的是:大多数的效能改进,对不同硬体的影响趋势是一致的。
因此,我们最有价值的测试方式是:
在固定硬体、固定设定与固定随机种子的情况下,测量开局初期的 模拟刻(tick)效能。
这让我们能快速重复测试,以追踪不同开发版本之间的速度变化,并能及时发现效能退化问题。
不过,有些优化在低核心数的硬体上无法充分发挥,例如:
早期游戏的模拟主要是单纯的运算吞吐量问题;
但後期游戏的优化则着重於控制系统复杂度的成长,例如角色数量、领地规模的暴增。
因此,我们仍会定期在低配电脑上进行检查,并分析终局存档,以避免只针对多核心处理器的平行化方案进行优化。
调整与取舍
软体工程界有句老话:「完美是优秀的敌人。」
若一开始就执着於让程式码达到「最完美、最高效」的状态,往往会导致开发周期无限延长。
这在游戏开发中尤其真实——我们通常会先实作出一个初版系统,再根据游玩回馈与实际乐趣不断修改、调整。
有时我们能预见未来会有潜在效能问题,会提前设计更合理的资料架构来减轻负担;
但多数情况下,更重要的是先让功能能跑起来、能玩起来。
在确定可行後,我们才会回头检查那些不符效能要求的系统,并从一致性与效率两方面加以改进。
千里之行,始於足下
以上是我们在开发资料片时处理效能问题的基本流程——但《普天之下》的情况完全不同。
这次的规模远超以往任何 DLC,不仅功能量更多,最大的挑战来自新增的两大片次大陆——东亚与东南亚。
这意味着模拟规模远超过以往任何一次扩展。
通常,未优化的功能新增会带来约 20% 的效能下降;
但这次,我们还必须面对 伯爵领(Barony)与统治者数量增加了 32% 的现实。
在我们的模拟中,每位统治者都是推动世界进展的最小单位,这与 CPU 的工作量几乎是线性关系。
换句话说——光是把整个亚洲放进地图,游戏速度就被迫放慢了相同比例。
因此,在《普天之下》的规划阶段,我们特地预留了额外的开发时间与资源,用於研究如何让游戏跑得更快、抵销扩张带来的效能负担。
我们也知道,光靠遵守程式撰写的「好习惯」是不够的——这次,我们必须更深入地检查那些旧系统中潜在的瓶颈。
接下来,让我们把话交给两位才华横溢的工程师 Anton 与 Carl-Henrik,
由他们说明我们如何在程式中发现效能低落的组件,并以「得快起来(Gotta go fast)」为原则进行优化。
专注於最耗能的系统
大家好,我是 Anton,《十字军之王 III》团队的资深程式设计师之一。
我在这个专案已工作多年。接下来我将谈谈我们如何组织程式架构,以及我们在效能改进上的思考方式。
效能优化的一种方法是:分析游戏中各个系统在每日模拟刻中所耗费的运算量。
我们会先从「最昂贵」的系统着手,因为优化这些部分能以最少的时间带来最大的效益。
各系统本身通常是相对独立的,与其他部分的连结有限,因此更容易针对性地理解与优化。
我们的内部工具能将这些游戏功能以视觉化方式呈现,方便比较每个系统对效能的影响,并快速辨识出需要优先处理的项目。
http://i.imgur.com/ImXAOdZ.jpg
图注:这张图展现了当游戏一次一项地执行运算时,它的效能表现会是怎样
这里举个例子:
我们把游戏内 25 年的模拟资料整合起来,显示游戏中各个系统平均花费的时间。
整个游戏共有 63 个系统会在每天的模拟刻更新;
其中 44 个系统每次更新都花不到 0.3 毫秒,因此几乎可以忽略。
剩下的 19 个主要系统,我们会在图表上显示它们的名称、平均耗时,以及每天所占的百分比。
有些系统天生就会比较吃效能。在开发过程中,不同系统会轮流占据这张图上较大的比例。
我们会评估「这个系统每天花这麽多时间」是否合理。
例如,有一段时间继承系统(succession)和局势系统(situations)曾位於图表顶端,这显然代表出了问题,需要进一步调查。
结果发现:
局势系统更新过於频繁,即使没发生变化也在浪费运算;
继承系统则在过多人身上执行了非常昂贵的脚本。
现在,这两者都被归入「其他(other)」类别中,运作已趋正常。
通常,角色(characters)与修正值(modifiers)仍是最耗资源的部分,这是游戏的核心,无可避免。
不过我们仍得不断思考:
「这些本来就很吃效能的系统,我还能让它们更快吗?值得再花几天时间去优化,还是该转向其他更容易的地方?」
平均值并不是唯一重要的数字。
这张图其实揭露了另一个问题——
你会注意到浅橘色长条(活动系统 activities)有时会突然飙高,导致某些月份的运算时间远高於平均。
我们的目标不仅是让整体平均时间低,还要避免在发生重大事件时出现明显的效能尖峰。
这也是这种「视觉化图表」比单看总平均数据更有用的原因。
目前看来,活动系统会是我们下一轮优化的首要目标。
并行更新 vs 单线更新
前一张图展示的是每日模拟刻中「单线(逐项)更新」的部分,
接下来的两张图则会展示「并行更新(parallel updates)」的效能表现。
http://i.imgur.com/ZQfNdYB.jpg
图注:AI 并行更新
http://i.imgur.com/71bvl8R.jpg
图注:游戏系统的并行预更新
以单执行绪方式开发系统非常直观。
(名词解释:执行绪(Thread) 是电脑运作中一段可以独立执行的程式流程。)
你能明确知道事件执行的顺序,一切都可预测、可重现。
这让开发过程更快,也能更早测试与平衡功能。
通常我们会先让功能的基本骨架在游戏中能正常运作,
之後再将它与其他系统连结,
接着再进一步将部分工作改为并行更新。
上面两张图展示了每日模拟刻中「并行更新」的情况。
你仍能看到每个模拟刻中实际花费的总时间(即墙上时间,wall-clock time),
每张图都低於 20 毫秒。
图中的红色粗线代表整体更新所花的时间,
可以看出同一时间内透过并行更新能完成更多工作。
此范例运行於一台约有 20 个逻辑核心的电脑上。
为什麽不全部改成并行更新?
因为多人游戏必须保持可确定的事件顺序,这样所有玩家端的游戏状态才能完全一致。
另一个重要原因是确保游戏逻辑的正确性。
游戏中大多数变化都会产生连锁效应。
举例来说:
一位统治者征服了新的头衔,意味着另一位统治者失去了它;
失去头衔会影响收入与军事力量;
变弱的统治者会更容易受到派系与敌人的威胁。
在这些过程中还可能触发额外事件。
若没有严格定义的执行顺序与连锁逻辑,我们将无法理解或预测游戏结果。
在明白这点的前提下,我们仍希望尽可能让更多工作同时进行。
我们有一套内部框架,能将功能分为「单线」与「并行」两个步骤。
这部分其实早在发售前的开发日志 #36 就提过。
并行部分会先执行,称为「预更新(pre-update)」。
在预更新阶段,游戏内不会发生任何可见变化,
所有并行执行绪都看到相同的游戏状态,就像世界被暂停一样。
在这个阶段,各系统可以同时进行大量独立运算,
计算出下一阶段(单线更新)需要修改的内容。
例如:
每个角色的收入都能各自独立计算;
每个 AI 行为者都能独立决策;
所有繁重的逻辑、触发条件与数学运算都可事先预算完成。
这样能大幅减少最後单线更新时需要处理的项目——
例如直接套用已算好的结果,而不是现场重新运算;
直接执行已决定的行动,而不是整个再跑一遍决策流程。
即使在单线更新阶段,我们仍希望善用多执行绪资源。
这部分风险与复杂度更高。
若能证明某些修改与执行顺序无关,或某些动作的副作用非常有限,
那就可以安全地在这里做并行更新。
另外还有一点要注意:
游戏中每天其实只有一小部分内容会更新。
我们将更新分为每日、每月、每年三种层级。
只有极少数关键系统需要每天更新,例如 AI 的部队移动。
大多数系统只需每月更新一次,这是效能与即时性的折衷方案。
每天只会更新大约 1/30 的人口、建设、疫情等内容,让昂贵的运算平均分散在整个游戏过程中。
相对於早期作品,这有一个明显的缺点:玩家无法确切知道这些事情何时发生。
你不会知道哪一天领到月收入,它只是「每 30 天发生一次」。
套用至具体系统的优化
接下来谈谈这些优化如何应用到具体的游戏系统中。
前面提过的「继承系统」就是一个例子。
《普天之下》加入了中国——一个庞大的帝国,拥有独特的继承机制。
无数人争夺伯爵领、公国与王国的头衔,
候选人依据个人、家族与人生事件的「功绩评分」排名。
某个阶段,这成为每日更新中最耗资源的系统之一,即使继承的更新频率本身已经很低。
为什麽会这麽慢?
因为中国有大量头衔要分配,
而原本的设计允许几乎所有人都能成为候选人。
这形成了一个「平方级」问题,复杂度极高。
在拜占庭帝国规模下还勉强可行,但在中国的庞大结构下完全不可用。
我们做的第一步尝试,就是改变运算顺序。
我们能否尽早排除不合格的候选人,避免对每个人都进行昂贵的分数运算?
从 4,000 人中选最优比从 100 人中选要慢得多。
接下来,把原本「逐一算分」的程序改为并行更新。
这项分数计算本身是独立、不会改变的,因此可同时对所有人计算。
光这样就让速度提升三倍,但仍不够快。
第三步:与设计师讨论设计初衷。
真的有必要让中国的每个廷臣都能竞争任意伯爵领吗?
我们决定折衷——
让无领地的贵族依然有机会,但将平民(lowborn)候选人限制在他们居住的地区。
这让候选人数减半,效能显着提升,同时玩家体验并未受损。
第四步:修正一个潜在问题。
经过上述三步後,大部分耗时都集中在脚本分数运算。
我深入检查,发现一个旧触发条件「地产收入」的快取机制错误。
由於引入了行政领地的「总督效率」後,原本简单的回传值变成即时计算,导致速度暴跌。
修正快取後,继承更新的耗时降到几乎可忽略,甚至在效能图中消失,归入「其他」类别。
同时,所有使用地产收入的脚本也跟着变快。
系统层级的优化经验
让游戏变快的另一种方法是减少不必要的运算频率。
事实证明,男爵级 AI 尝试执行了许多不必要的行动。
例如,男爵既没有内阁,也没有宫廷职位,但系统仍在为他们评估这些项目——现在不再如此。
若建筑一栋建筑需要三年时间,
那他们也只需每三年尝试一次新的建设。
许多决议与互动对男爵而言根本无法成立,既然如此,就不该让他们去检查那些触发条件。
我们针对统治者等级重新审查了可用机制,进一步节省时间。
不过,实际效果并不惊人,
整体每日模拟刻只快了 0.5 至 1 毫秒,
容易被硬体或当前游戏状态的随机波动掩盖。
原因很简单:
高阶统治者的运算量远超男爵,优化男爵带来的影响有限。
而且 AI 决策本身早已并行更新,
因此所有的效能提升都分散在多核心上,不太明显。
我这部分就到这里。
感谢让我有机会分享关於效能的思考。
接下来交给 Carl-Henrik——他在《普天之下》的开发中也做了大量效能优化工作。
全貌
致每日模拟刻爱好者们:
我是 Carl-Henrik,团队的首席程式设计师,主要负责改进《十字军之王 III》的效能与记忆体使用。
我的个人兴趣是用 8 位元与 16 位元 CPU 撰写组合语言,
因此效能优化可说是我最热爱的领域。
我甚至赢过几场程式码体积/效能竞赛!
我算是团队的新成员,因此非常依赖身边的夥伴——
包括 Daan、Joel、Jimmy、Anton,以及设计团队与其他开发同事。
(顺带一提,我曾在 Johan Andersson 加入 Paradox 前指导过他。)
通常我发现原本运作良好的程式码,
在游戏後期因新增了大量头衔与角色而不再符合最初假设时,
就正是改善效能的契机。
这并不是因为原始程式码不好,
而是因为游戏规模成长,让它不再符合需求。
载入阶段
我最初的重点是游戏的载入画面。
由於我家里的电脑低於 CK3 的最低规格,优化载入阶段能大幅改善我自己的游玩体验。
我没料到载入过程中有这麽多活动,
而当时唯一的效能测试方式是侦错日志,它与其他载入过程交织在一起,难以分辨。
为了更好地分析载入时间,我开发了一个新的效能追踪工具,能记录整个载入序列,如下图所示。
图表显示每个 CPU 在载入或设定内容时的工作情况。
其中的黑色区块不一定代表 CPU 闲置,也可能是载入动作太快未被显示,或该部分未包含在载入函式之内。
http://i.imgur.com/pptuCrI.jpg
图注:串流效能分析工具——我目前的个人开发时间(PDT)专案
虽然我们找出了许多可改进的部分,但要全面实施这些变更在当时的工作量实在太庞大。
我打算不久後开始着手强化这些系统。
记忆体
在《草原大汗》发行前後,我们需要进一步节省 RAM。
最低规格电脑在执行游戏时出现困难,而这部分早先其实已由我们的主机移植团队进行过研究。
能将整个《十字军之王 III》完整移植到现代平台,本身就是一项壮举,
而得益於他们的成果,我们得以相当快速地完成记忆体优化。
其中一项特别有效的改进,是游戏中提示框(tooltip)的记忆体使用量。
结果相当令人惊讶——只靠这一项改动,就让 PC 版节省了数 GB 的记忆体!
我们也研究过 Clausewitz 引擎中新 GUI 程式码所带来的记忆体节省,
但最终发现其结构与《普天之下》的需求差异过大,无法直接采用。
效能
在完成记忆体优化後,我们也需要检视程式效能。
早期测试显示,《普天之下》的效能相比前一款资料片《草原大汗》下降了约 1.5 倍。
我的做法是以程式码层面的改进为优先,
而其他专注於设计面的团队成员,则主要针对脚本与角色行为频率等游戏内要素进行优化。
http://i.imgur.com/QRQduCz.jpg
图注:来自工作电脑(32 核心)的 100 年效能取样图
为了追踪优化进度并侦测与开发相关的问题,
我每天都会执行一次效能分析,模拟游戏内 100 年的运行。
这项测试会同时在两台电脑上进行:
一台是高阶机种(32 核心处理器、64 GB 记忆体、Windows 11),
另一台则是较低规格的电脑(8 核心处理器、16 GB 记忆体)。
http://i.imgur.com/8mIWmXF.jpg
图注:来自低规格测试电脑(8 核心)的 100 年效能取样图
从这些效能图表中,我们可以针对众多系统进行分析,以找出潜在的效能问题。
一旦确认是哪个系统出现异常,并追踪到相关(执行较慢的)程式码後,我们就能开始进行优化。
多数情况下,我发现问题都来自「某些系统在更新其他根本不需要更新的东西」。
举例来说,在「预更新(Pre Update)」的效能图中,脚本变数(Script Variables)曾是耗时最高的部分之一。
在储存变数/脚本变数(Saved Variables / Script Variables)中,我们重新缩小了需要检查的范围。
原本每次模拟刻要检查约 50 万个变数,现在只需测试几百个即可(因为只有这些变数会因逾时而失效)。
这项修改让整个类别在效能图上彻底消失。
绘图(Rendering)
图像运算通常是游戏中最耗资源的部分之一,
但即使在新版地图更新後,《十字军之王 III》在这方面的影响仍不大。
为了进一步提升图形效能,我们新增了「自适应帧率(Adaptive Framerate)」功能。
这项设定能让拥有 少於 10 个处理器 的电脑在画面活动不多时,自动微幅降低渲染帧率,以节省运算资源。
此功能会随「低画质」预设设定自动启用。
自适应帧率与最大帧数(Maximum FPS)设定一同运作,
而最大帧数 现在新增了一个预设选项:「显示更新率(Display refresh rate)」。
(译注:将最大帧数预设为萤幕刷新率。)
在过去,如果关闭垂直同步(VSync)又未限制最大帧数,会因为帧率预设为无上限而造成明显的效能下降。
若想在画面影响最小的情况下获得最佳效能,建议启用自适应帧率,并将最大帧数设为 30 FPS。
新版地图与其他美术改进确实增加了 GPU 的处理负担。
这可能导致画面更新速度下降、介面反应稍慢。
不过,这并不会影响每日模拟刻的速度,
因为 CPU 与 GPU 是并行更新(即多执行绪同时运作)。
我们仍计画进一步研究如何有效地平衡这两者的负载,
只是这项优化暂时还未被列为最高优先级。
复杂性(Complexity)
许多优化都相对直接、容易理解,
但有时一些看似无害的小问题,却可能让你陷入深不见底的麻烦。
有一个函式会进行几项检查,若通过则执行对应脚本。
整段程式码约 30 行,但其中的效能问题多到让我花了 超过两周 才完成改进。
其中最慢的一行是呼叫 IsScopeOK,
它的功能只是检查「脚本作用域(scope)」是否符合该触发条件或效果所预期的范围。
尝试一些微小优化後毫无改善,
这表示编译器早已自动处理了那些低层级的效率问题。
虽然这个函式本身并不算慢,
但由於游戏在每个模拟刻中会执行极大量的脚本,
这段程式成为整个游戏最吃效能的部分之一。
深入分析後发现:
为了检查作用域,每个触发条件(Trigger)都会生成一个 128 位元的旗标栏位(bit flag field),
并与作用域生成的另一个 128 位元栏位比对。
我们将这部分改为直接比较作用域的「编号」而非整个旗标栏位,效能因此大幅提升。
不过,触发条件与效果可以接受多种类型的作用域,若初次比较失败,仍需回退使用旧的 旗标 验证。
尽管如此,这已经是极大的改进。
在大多数情况下,触发条件与效果都会回传作用域编号,
但还有一种称为「连结(Links)」的例外类型,它们只回传 旗标。
我花了两天时间逐一检查所有这些类别(class),并补上缺少的函式,
让整体结构更一致、效能更稳定。
http://i.imgur.com/8c1FxPd.jpg
图注:重写後的 IsScopeOk 程式区块:将耗时较低的检查项目移至最上方
触发条件(Trigger)与效果(Effect)似乎也遭遇了快取失误(cache miss)问题,
加入快取预取(cache prefetch)後,效能又略有提升。
不过,这只是整个函式中的一行。
我们有一个内建的脚本效能分析工具(Script Profiler),用来大量测试并提升脚本效能。
理论上这个工具只有在使用时才会造成效能负担,但我们仍进一步调查了它的运作方式。
我们需要记录脚本的档名与行号,
而该资料类型在储存这些资讯时的实作效率并不高。
改进後确实带来不错的效能提升。
不过在非使用状态下,这样的效率仍属多余开销,
因此改为使用「就地配置(in-place new)」而非预设建构函式,
让这行程式的效能终於达标。
虽然过程耗时,但每一步的实验、测试与分析,都对最终的效能提升极具价值。
简化(Simplicity)
有时候,让系统更简单也能让它更快。
游戏中每位角色都对其他角色有许多「好感度」数值,
而这些数值的强度会随时间变化。
原本的系统会将角色间的「当前好感度」快取起来,同时计算出「下一次变化 1 点的日期」。
为了取得目前的好感度,系统只需从快取中找到该值,
并在每天检查是否到了变化时间。
这个检查存在一个排序清单中,只需处理即将变动的那些好感度。
然而,每当好感度变化後,新日期都必须重新插入清单中。
随着角色数量增加,这个操作反而越来越昂贵。
後来我们发现,好感度的变化其实只是一次简单的乘法与加法,
因此移除快取、改为「即时计算」反而更快,
也不再需要维护那个排序阵列。
失败(Defeat)
有时候,我尝试优化某个函式,结果发现整体效能并没有因此变好。
举例来说,
「查询修正值(modifier values)」是每日模拟刻中非常频繁的操作,
理论上若能加速这段程式,效益应该很大。
我尝试了两种方法,确实让函式本身执行时间大幅缩短,
但同时却导致其他系统变慢,整体效能并没有任何净增益。
因此,即使花了不少时间修改,这些变更最终仍被放弃。
从脚本与设计角度的效能
大家好,我是 Daan,《十字军之王 III》的资深程式设计师,
同时也是《普天之下》的程式开发协调员,并担任中国区域的设计负责人(feature steward)。
因此,我非常适合来谈谈我们在设计与脚本层面如何改善效能。
需要说明的是,大部分脚本微调并非我亲自撰写,
但我提供了工具与建议来辅助这些改进。
优化脚本(Optimizing our Script)
我们的游戏脚本以文字档形式存在,负责实现大部分的游戏机制。
它们给了设计师以及模组作者强大的控制权。
不过,强大也带来责任与代价:
Paradox Script 的执行速度远不如 C++,而且很容易一不小心就让程式变慢。
为了改善这点,我们在近几次更新中新增了多项工具,可帮助我们找出慢速脚本。
例如「脚本效能分析器(Script Profiler)」
在开发者模式下即可於游戏内直接使用。
透过这些工具,我们几乎检查了所有脚本档,寻找效能提升空间。
我们重新排列触发条件的顺序、简化结构、使用「功能相同但略快」的微型优化手法,等等。
我在此也向喜欢保持脚本原样的模组作者致歉——
我们为了效能,确实改动了不少内容!
我们也针对最常用的触发条件与效果,在 C++ 端进行优化。
有时甚至会新增新的触发条件,
例如那个名称有点拗口、但非常贴切的:「is_available_quick 触发条件」。
http://i.imgur.com/LYm6hjC.jpg
图注:自动生成的脚本文档,显示出触发条件「is_available_quick」
这个新的触发条件能让我们一次检查原本需要分开测试的多个「是否可用」判定,
因为我们发现这些判定常常会被一起用到。
它的逻辑效果和逐一执行每个判定时完全一样,只是现在整合成了一个更聪明、更快速的 C++ 程式区块。
同样地,我们也在多个脚本清单生成器中加入了常用筛选条件的捷径选项,
只要在文字上做些小改动,就能让脚本执行得更快。
脚本顺序优化器(Script Order Optimizer)
我们也开发并实作了一个自动脚本顺序优化器,会根据设定的权重自动调整脚本执行的顺序,
让它在符合条件时可以提早结束运算,节省效能。
不过,目前我们决定暂时停用这个功能,因为它带来的效能提升不太稳定,也不一定明显。
这正是效能优化常见的情况:一项优化的成效可能被另一项抵销。在这次的例子里,其他脚本层面的改进已经让这个工具的效益变得有限。
如果未来发现它在统计上确实有用,我们还是会重新启用。
不管怎样,这项技术仍会用在未来改进脚本语言的元编程上。
如果你有兴趣,可以在启动游戏时加上「-script_optimizer」参数来启用它的基础版本。
我可能会在之後的开发日志里再详细介绍这个工具及它的选项。
弹性频率(Flexible Frequency)
有时候,我们的模拟会执行一些其实没必要的内容——对某些角色来说完全没意义,或变化频率极低。
过去脚本的逻辑并没有办法让 AI 根据角色类型聪明地调整执行频率。
举例来说,冰岛的一位男爵和中国的皇帝在旧系统里会以相同频率考虑角色互动,这显然不合理。
因此,我们调整了多个系统(例如互动、决议等),让它们可以设定不同头衔等级的 AI 检查频率。
这样我们就能清楚定义,不同等级的统治者该多久考虑一次某个行为,甚至可以设定他们永远不需要考虑(频率为 0)。
举例来说,在游牧、曼荼罗政府制和瓦努阿政府制中,有一项互动叫「release_as_tributary_interaction」(释放为朝贡国)。
男爵或伯爵应该会考虑这项互动吗?
不,完全不会,因为他们在游戏机制上根本无法这样做。
公爵呢?也许可以,但这对他们来说并不重要。
然而在旧的逻辑中,系统仍会让每位统治者每年进行一次昂贵的检查。
现在有了依等级区分的 AI 频率设定,我们可以直接跳过这些不必要的运算,把这类互动归入「永不检查」的类别。
而这种「永不执行」的情况,反而是最容易优化的。
http://i.imgur.com/si0Euwa.jpg
图注:「release_as_tributary_interaction(释放为朝贡国)」互动的 AI 执行频率设定
一个额外的好处是,这项改动让高等级 AI 统治者能更频繁地评估行动,而不会因低等级角色的存在而拖慢效能。
这代表在关键时刻,AI 的反应会更即时。
我们已将这种依头衔等级区分频率的设定方式,套用到几乎所有角色的互动、决议、活动与大型工程中
总计大约 550 种 AI 在游戏中可能考虑采取的行动。
清理闲置角色(Eliminating Stray Nobodies)
市面上有一个相当常见的提升效能模组叫「人口控制(Population Control)」,
它会在世界人口达到一定数量後开始删除角色。
我们虽然没有采取完全相同的做法,但针对相同的根本问题进行了优化:
游戏世界会累积大量几乎没有任何作用的角色,而经过几百年後,这些角色可能多达上万。
因此,我们减少或移除了多个会生成无聊、无用或不可见角色的来源。
这些角色原本常停留在宾客池、男爵或伯爵的宫廷边缘,只占记忆体又消耗效能。
同时,我们保留那些有故事背景的有趣角色,让他们在事件中登场更频繁,取代那些随机生成的无名之辈。
这样的调整有效减少了长期游戏中不必要的角色累积,降低了非统治者角色对模拟系统造成的负担。
结语
让我们看看目前的成果吧
在撰写这篇开发日志时,距离发售仅剩数周。
我们一开始测得每日模拟刻速度下降了近 1.5 倍,因此设定目标是让最终版本的速度仅比前一版稍慢。
这次我们扩增了相当大的地图区域,也因此增加了大量角色。
如今进入开发的最後阶段,每天都在进行调整与修正,但游戏效能已大幅改善。
目前版本的运行速度与现行正式版几乎相当,甚至更接近我们最初设定的理想值。
这项成果已在高阶与低阶电脑上双重验证。
我们仍希望在最终收尾阶段能再把速度提升一点。
尽情高速游玩吧!
最低硬体需求更新(Updated Minimum Hardware Specs)
最後,由 Studio Black 技术总监 Jimmy 带来关於最低硬体需求的补充说明。
首先,我必须说,我对团队在《普天之下》这个技术要求极高的资料片中达成的效能成果感到非常惊艳。
作为效能审查的一部分,我们重新检视了最低硬体需求,特别是 CPU 的基准线。
正如本篇日志所述,经过数月的优化,我们几乎完全消除了早期开发时的效能下降。
从最初每日模拟刻耗时大幅上升,到如今的表现已接近现行版本(在游戏前期与後期间仍有些微差异),
即使在地图扩张与模拟负载增加的情况下,依然维持稳定。
这些测试同样在高端与低端硬体上完成。
换句话说,这次的硬体需求更新并不是因为程式没优化,而是为了确保所有玩家都能稳定运行游戏。
在硬体实验室的广泛测试中,
我们发现一些较旧的 CPU,例如 2011 年推出的 Intel i3-2120,在高负载下难以保持稳定,
特别是搭配仅 6 GB 记忆体的系统时更明显。
这款处理器是我们 2020 年原始的最低需求,对一款将近十五年的硬体来说,能支撑这麽久相当惊人。
但为了确保游戏体验一致,我们现在将最低 CPU 建议更新为 Intel i5-750 或 AMD FX-4300,并搭配 8 GB 记忆体。
这样的配置以现今标准来说仍算中等,但能提供《十字军之王 III》在发售五年後所需的稳定、可预期效能。
(译注:讲了这麽多,还是有些人的硬体要提升啊,不过至少有说服到我,各位版友,年关将近,该提升的东西就顺便升级一下吧!)
-----
Sent from JPTT on my Samsung SM-N950F.
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 49.216.16.205 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Paradox/M.1760538958.A.A5B.html
1F:推 Prometheus2: 推 10/15 23:51
2F:推 StSoSnE: 所以结论是在拓展了地图後 他们能优化处理速度到跟当前 10/16 02:43
3F:→ StSoSnE: 版本一致 後期该卡还是得卡 10/16 02:43
4F:推 KenWang42: 祖传引擎能做到这个程度很屌了 10/16 08:31
5F:推 Comartin38: 官方补充:历史资料中最早的天子是光武帝(西元25年起) 10/16 11:18
6F:→ Comartin38: 之前的大概就用一段介绍带过(秦朝-西汉-新朝) 10/16 11:19
7F:推 Dannyx: 我以为CK3是用新的引擎了 10/16 12:59
8F:推 ck901372: 现在後期就很卡啊,明目张胆说会卡 10/16 13:41