[CK3 ] 開發日誌#187(普天之下) 效能與優化
譯註在前:
挖塞,整個歐亞大陸都要納進來,我的電腦一定跑不動啦
你也跟我有一樣想法嗎?
今天官方就要對這個議題來場直球對決,我們來看看他們怎麼說吧
正文開始:
我是 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://www.ptt.cc/bbs/Paradox/M.1760538958.A.A5B.html
推
10/15 23:51,
4小時前
, 1F
10/15 23:51, 1F
推
10/16 02:43,
1小時前
, 2F
10/16 02:43, 2F
→
10/16 02:43,
1小時前
, 3F
10/16 02:43, 3F
Paradox 近期熱門文章
13
35
PTT遊戲區 即時熱門文章
32
103
71
281
48
99