效能表現提升:《特戰英豪》的通用無效化(Global Invalidation)
大家好!我是Aaron Cheney,是任職於《特戰英豪》遊戲效能團隊的軟體工程師。效能是維持《特戰英豪》競技公平性的關鍵要素,而我們的團隊是負責監控、維護,以及提升伺服器和用戶端的效能。
我們有個功能經過數個月的開發,現在我們很高興能跟各位分享最新消息:通用無效化(Global Invalidation,即4.03版本更新公告中提及的「介面局部更新」)。我們待會就會詳細說明這個功能,但首先我們先花點時間來看看,這個功能從4.03版本以來,如何影響用戶端的效能。
暴雷警告:這真的很讚。
通用無效化為我們大部分的玩家提供了顯著的效能提升。事實上,這是自遊戲發行以來,幅度最大的一次效能提升。
雖然這些圖表很令人振奮,而且我們也很高興有這樣的成果,但重點還是要了解你眼前所看到的東西。我們處理龐大、複雜的資料集,透過組織、篩選並控制資料來了解玩家的體驗。為了有全盤的了解,以下是你應該記得的要點:
- 圖表顯示的內容是不同「版本」間「平均幀率」的變化,數字越高越好。
- 每一條線代表玩家常用的各種硬體配置(CPU+GPU的組合)。分析效能資料時,我們認為這些組合對於預期效能來說,是最重要的依據。具有相同CPU+GPU組合的電腦,會在這些圖表中彙整在一起。
- 資料樣本是從兩種列隊取得:一般模式和競技模式。這兩者是《特戰英豪》中最熱門的遊戲模式,因此我們花了非常多心力來了解並提升其效能。
- 我們排除了不滿10個人的對戰場次。這能確保離群值不會讓資料失真(玩家人數較少的對戰,效能會較好)。
通用無效化重點摘要
通用無效化能使CPU密集型的用戶端(通常是中高配電腦)效能最多提升15%。這些效能提升是由多個團隊花了數個月的心力才達成的。我們找到了遊戲中亟需改良的部分,並在過程中做好風險管理,確保玩家能有穩定的遊戲體驗。
誰能受益,以及調整期望
根據我們的即時計量,通用無效化使CPU密集型的用戶端(通常是中高配電腦)效能最多提升15%。
雖然在彙整資料中看到明顯上升的趨勢,但這不代表每分每秒的遊戲過程效能都會提升。另外,這不保證每台擁有相同配置的電腦都能得到相同的結果。
這表示CPU密集型的電腦,在《特戰英豪》上的效能基準線普遍提升了,但你個人的電腦效能還會受到其他因素的影響,畢竟每個人的電腦狀況都不一樣。
了解通用無效化
在我們正式介紹通用無效化之前,我們首先要解釋一下Unreal Engine中的UI元素。
小工具和樹狀結構
UI元素(又稱為小工具)是利用樹狀結構,由更小的建置組塊所製作而成。樹狀結構就類似電腦上的檔案系統。一個小工具可以有多個子系統(就像一個資料夾裡可以有很多檔案一樣)。
這些建置組塊可以組合成複雜的小工具。舉例來說,我們的彈藥計數器由許多部分組成,而它的樹狀結構大概長這樣:
如果把彈藥計數器的建置組塊全部合在一起,就會像這樣:
(上方的綠色外框是為了清楚說明而刻意分開標示,不然其實很多線都會重疊在一起。)
每當樹狀結構中有一個以上的小工具有所改動時,也可能會影響其他好幾個小工具。舉例而言,當一個小工具移動到畫面上的新位置時,它底下的所有小工具也必須跟著調整位置。這些改動是透過名為「無效化」的系統來管理,我們會在下一個部分進行說明。
無效化
無效化是Unreal Engine中的一個機制,用來表示特定的小工具有所改動,所以必須要更新。
小工具會因為各種原因而需要進行無效化:動畫、顏色、透明度、尺寸、排序、文字、圖像等等會隨著遊戲內的情況而改變。當小工具改動時,系統會判定其「無效」,所以需要更新。
更複雜的是,小工具有各種類型的無效化。常見的類型包括:
- 版面配置(Layout):當小工具尺寸改變時(非常消耗效能)。
- 繪製(Paint):當小工具的外型改變,但尺寸維持原樣時。
- 子系統排序(Child Order):當樹狀結構中的小工具改變順序時(同時跟版面配置有關,因此也非常消耗效能)。
- 可見度(Visibility):當小工具的能見度改變,變為隱藏或顯示的時候(同時跟版面配置有關,因此也非常消耗效能)。
這些類型的判定是用來了解,應該執行哪些操作,才能夠正確地將小工具繪製出來。
當小工具之間有連動關係時,情況就變得更複雜了。小工具會分成不同階層,而其版面配置會受各種因素影響。一個小工具要無效化的話,可能需要連帶更新其他相關的小工具,才能夠正確地繪製出來。舉例來說,如果多個小工具排成一個直向版面配置(像是社交介面裡的好友名單),而小工具的排序改變了(像是好友上線),直向版面配置內的所有小工具都需要更新。
這樣的系統有幾個目標:
- 盡量減少小工具的無效化。這會減少為了要正確繪製,而需要更新的小工具數量。
- 只在必要時更新小工具。不適當的無效化,會浪費寶貴的CPU週期。
- 當小工具不需更新時,把結果存入快取以便快速在每一幀繪製出來。如果什麼都沒變,那麼CPU週期就可以被省下來。
這些幕後工作的解釋應該足以讓大家了解小工具如何更新,以及什麼情況會造成無效化。接下來,我們要看看開發人員如何實際使用此功能。
無效化框
Unreal Engine提供了名為無效化框的要素,用來把多個小工具組合起來。在同一個無效化框的所有小工具,都不會進行預處理(pre-passed)、更新或繪製,且結果會存入頂點緩衝區。
每當無效化框中的小工具更新時,就會丟棄原本的快取資料,然後小工具會再更新並重新繪製。雖然如果單看一幀,重新整理快取檔案的效能負擔可能很大,但長期來看,這樣分攤的效果反而是更好的。
《特戰英豪》的UI效能要良好,無效化框扮演重要的角色,在我們如火如荼準備發行遊戲時尤其關鍵。然而,使用上還是有一些限制:
- 開發人員必須知道哪些小工具適合放在同一個無效化框裡,經常更新的小工具就不適合這個方法。
- 開發人員必須手動將小工具放進無效化框。不太可能把遊戲中所有小工具都這樣手動處理,因此開發人員得知道哪些小工具有放入無效化框的價值。
想閱讀更多關於無效化框的內容,請查看Epic Games的說明文章。
現在,我們有足夠的背景知識來討論通用無效化了!
通用無效化登場
聽到現在,你可能會覺得:「幹嘛不把所有UI要素都放到一個通用的無效化框裡就好?」嗯,那差不多就是通用無效化的作用。
通用無效化的目標是,大幅提升整個遊戲的UI效能,同時減少開發人員需要手動把小工具放進各個無效化框的工作。這是個兩全其美的辦法。
然而,目前Unreal Engine 4.25(《特戰英豪》所使用的Unreal Engine版本)當中,並不是所有類型的小工具都支援通用無效化。後來的Unreal Engine版本有進行改善,但《特戰英豪》無法馬上換成新的版本。另外,我們還不是非常了解,通用無效化究竟會使《特戰英豪》的效能提升多少。
我們的工作就此展開。
為什麼我們決定要下這個功夫?
2021年7月底,團隊決定在內部遊戲測試時測試通用無效化。我們做出一些小改動來修正幾個錯誤,讓遊戲測試可以順利完成。不過,我們原本就預期遊戲測試時會遇到bug,最後也的確發現了不少。
那次遊戲測試結束時,我們找到了大約20個bug,這些還只是比較明顯的那種。我們很有可能還沒看到比較細微、不容易發現的錯誤,更不用說某些需要用特定方法測試的極端案例。
但是……通用無效化究竟有沒有讓效能提升呢?絕對有。
分析從那場測試中得出的資料後,我們發現使用者介面效能比以往高出35%。(註記:使用者介面僅占每一幀的部分效能。)
然而,我們還有其他待解的問題:
- 要修正所有bug需要多少時間?
- 那些團隊應該負責那些工作?
- 比起其他排定的工作,這件事應該更優先處理嗎?為了可以常態性地推出新內容,我們的時間表通常早在數個月前就預先計畫了,而像這種突發工作,都很不容易排進時表,不管它多讓我們感到振奮。
- 修正錯誤會不會影響我們提升效能的主要目標?修正所有的錯誤需要重寫非常多的程式碼,每一條都有可能拖累使用者介面的效能。
- 我們什麼時候該著手進行?我們知道在Unreal Engine的後續版本,介面局部更新也正在積極開發中,這表示我們需要思考一下我們的時間軸,來和Epic整合這些改動。
最後,有幾個理由讓我們決定著手製作。
Unreal Engine整合與時機考量
雖然Unreal Engine 4.26和4.27版的通用無效化開發已經有了相當的進展,但《特戰英豪》不會跟著最新進度立即進行整合。我們不會立刻採用「最尖端」技術的理由是,我們必須考慮風險,並確保玩家獲得最穩定的體驗。
時間表中排定,在未來數個月內我們還是會繼續使用Unreal Engine 4.25版,這表示玩家必須在一年之後才能享受到效能提升帶來的好處。這我們沒辦法接受。
想詳細了解關於《特戰英豪》對於Unreal Engine升級的看法,請查看這篇《特戰英豪》技術總監Marcus Reid的推文串。
已知效能提升
就效能方面的工作來說,通用無效化提供了一個非常獨特的價值:觀測值。在內部遊戲測試中,我們觀測了可能的效能提升值,而達成那個數字的方法也(幾乎)已經很具體了。
效能方面的工作是很困難的。這不是一口氣進行的大規模工程,而是一點一點堆砌起來的;一些細微的改動能夠在長期增進整體效能,但能更讓效能直接提升兩位數的單一改動,是非常罕見的。這對最佳化而言,實在是難以抗拒的誘惑。
即使顧慮到會因錯誤修正而減少效能提升,通用無效化仍是我們的最佳機會,在合理的時間內用來帶給玩家顯著的效能提升。
我們是怎麼辦到的?
雖然最初針對通用無效化的嘗試早在2021年7月下旬就已經展開,但直到2021年9月下旬,我們才開始進行穩定此功能的工作。
選擇性整合Epic的改動
我們不可能完全整合Unreal Engine 4.26和4.27版,但我們知道Epic積極地在開發通用無效化,所以決定在這幾千條改動中翻找出適合的那些項目,讓這次的通用無效化功能更加穩定且完善。
僅整合部分改動並不是一件容易的工作。很重要的是,盡可能不要修改引擎的核心功能,才能在取用所需的改動時,一邊保持它的穩定。所有的工作都是在《特戰英豪》主要分支以外的分支進行,避免影響其他開發者。
在選擇性整合Epic的改動到我們的引擎裡之後,我們又花了數週的時間來盡可能的修正錯誤,同時準備將通用無效化帶到《特戰英豪》的主要分支中。過程中我們還做了一個開關,來讓我們快速開啟和關閉這個功能(要是事態一發不可收拾的話)。
在我們修正了很多bug,加入了許多Epic在4.26和4.27版進行的改動之後,就把獨立分支整合進了主要分支裡。
找出錯誤之間的共通點
雖說通用無效化的很多bug會以各種不同方式顯現,但往往能夠追溯到同一個問題來源。這些是最值得修正的bug,因為只要一個改動就可以解決很多問題。例如光是一個改動,我們就修正了出現在遊戲各處10個以上大大小小的bug。對問題源頭的仔細分析讓我們找到穩健的解決方式,從而提高通用無效化的可靠性和穩定性。
找出錯誤、修正錯誤、遊戲測試、從頭再來
接下來的數週和數個月間,我們平常的作業流程就是:在遊戲測試前啟用通用無效化、找到一連串的bug、在遊戲測試後停用通用無效化,然後修正那些bug。
每經過一次這個流程,回報的錯誤數量就越來越少。做個比喻的話,原本bug的數量多到像一條奔騰的溪流,在我們逐漸糾錯之後,漸漸變成涓滴細流,最後終於乾涸停止。
到2021年11月底,所有重大問題都已經解決,通用無效化也趨於穩定。
重大錯誤
- 亞星卓會讓遊戲當掉:曾經有一段時間,亞星卓玩家一進入對戰讀取畫面時遊戲就會當掉。這個bug在整合了Epic的改動之後就解決了。
- 多重繼承崩潰:C++裡的多重繼承是一個棘手的問題。簡單來說,就是特定類別中的破壞者順序沒有正確地依序執行,而導致當機。只要將兩條程式碼互換,來改變多重繼承的順序,問題就解決了。想更詳細了解多重繼承,請查看此文。
- 聊天室音效無限播放:在選單中,當你將滑鼠移動到聊天室欄位上時,它會播放音效。令大家感到煩躁的是,之前有個bug導致該音效會在一秒內播放多次。在修正這個bug的過程中,我們了解到了小工具怎麼樣在一幀之中多次接收滑鼠指令的時機,進而修復錯誤。
測試方法
我們必須特別謹慎應對通用無效化並進行完整測試的其中一個因素是,它會影響遊戲的每一個方面,沒在開玩笑。
這包括你的好友名單嗎?當然有。你要列隊的時候所按的按鈕?那也會。設定選單?這還用說。你的爆頭率呢?這個嘛……
重點是,UI元素會出現在於遊戲的每個角落,而且經常要傳達重要訊息給玩家,所以任何UI設計都不允許出錯。
為了達成目標,我們的QA部門(Quality Assurance,品質保證)研擬了一個融合多種測試方法的測試系統,來確保通用無效化沒有出錯。
垂直切面測試
《特戰英豪》的垂直切面代表玩家在遊戲中的主要操作體驗,從啟動用戶端、開始列隊、遊玩整場對戰,到查閱結算畫面。聚焦在遊戲最重要的部分,能讓QA人員快速測試玩家最常使用的遊戲要素,並盡早發現問題。
破壞性測試
垂直切面測試結束後,就是破壞性測試出場的時候。這類型的測試專門用來找出非常態性的問題,通常是透過一些外在因素(像是網路PING值、幀率、切視窗等等)的調整來達成。QA部門會利用一套內部工具,花上數週的時間來進行破壞性測試。
罕見案例測試
《特戰英豪》的許多環節只有一小部分的玩家會體驗到,而遊戲的某些環節只能體驗一次(例如新手教學與迎新活動)。只因接觸那些環節的頻率較少,並不代表它們不重要。我們找出並測試了所有罕見案例,這協助到我們抓到潛在的錯誤。
PBE(公開測試伺服器)測試
PBE是通用無效化的重大里程碑。
- 這是玩家與這項功能的第一次接觸,這表示我們能在「真實世界」的情境下測試通用無效化。
- PBE包含了多種硬體規格。PBE刻意將低階至高階的規格囊括進來,而在種類和機型如此繁多的玩家電腦上測試,讓我們對通用無效化在其他更多玩家電腦上的表現很有信心。
經過2022年1月22日那個週末的PBE測試後,我們有信心通用無效化不會影響公平性,而且效能提升的程度與我們的評估一致。
推出通用無效化
在4.03版本通用無效化推出後,我們密切觀察玩家回報的錯誤,同時也緊盯著效能相關的數據,以確保我們的估算與成果一致。總結而言,通用無效化對提升玩家體驗而言是個巨大的成功,我們希望各位喜歡更佳的幀率。
現在,通用無效化已經送到玩家手中了,效能團隊要回去繼續幫遊戲找到更多提升的空間。下次見,祝各位玩得愉快!