謝邀,就引用一篇之前我們家製作人大大的內容吧~

戴森球與行星級生產基地

目前這個存檔的遊戲時間是118小時。

遊戲玩到後期卡嗎?這也許是大家最關心的問題之一。

數千艘運輸機在忙碌,數千座設施在運作,數萬個太陽帆在環繞,數十萬貨物在運送,斗轉星移,地面上所有太陽能板都面朝著太陽… 這計算量可不是鬧著玩的!而以上還只是這一個星球。

本篇我將主要介紹為了保證遊戲的流暢性,我們是如何實現遊戲性能優化的。由於該話題涉及的內容與技術細節實在太多,所以我打算將優化系列分為三篇開發日誌,粗略的談一下我們所用的方法與技術。

遊戲的幀率機制

遊戲中的幀率分為渲染幀物理幀

渲染幀主要負責渲染遊戲畫面;

物理幀主要負責運行遊戲邏輯。

我們在遊戲中製作了幀率計數器以監控實時性能,其中左邊的數字是渲染幀,右邊的數字是物理幀。也可以在設置面板中設定渲染幀的幀速率。當開啟垂直同步時,渲染幀速率會和顯示器刷新率一致。

幀速率越高,GPU的使用率也就越高,當使用率接近100%時,就會自動降低畫面幀率。

在遊戲的生產系統中,我們需要一套能精確量化,服從「決定論」的邏輯,即同樣的操作只能導致同樣的結果。要拋開幀率帶來的影響,首先是遊戲中所有的時間必須按物理幀計數,例如製造時間為3秒的「電弧熔爐」,其實在內部邏輯里就是180個物理幀。再例如360kW的工作功率,在內部邏輯里其實是每個物理幀消耗6kJ的能量,頗有一種「量子化」的感覺。

根據以上的邏輯,負責遊戲邏輯的物理幀必須相對穩定,不能被渲染幀率所影響,否則玩起來就會感覺時間一會快,一會慢,所以我們將物理幀率鎖定為60幀,只有當渲染幀率太低時,才會折減物理幀率,以免塞幀。

使用DOP來代替OOP

DOP和OOP分別指「面向數據編程」和「面向對象編程」。具體的比較可以寫好長一篇文章,而且前人已充分討論,所以這裡就不贅述了。簡單來講,在面對遊戲中大量物件的情況下,面向對象會造成許多不必要的開銷,造成性能低下,而面向數據編程則將對象中的屬性逐一拆分出來,形成緊密排列的數組,使得相關邏輯能夠更快速的進行遍歷,甚至一些數據還能直接傳給GPU來處理。

那麼為什麼大家不都用DOP來代替OOP呢?這是因為「面向對象」更符合人們的認知和代碼書寫習慣,也便於項目管理,而「面向數據」的代碼寫起來有一些反人類,有時甚至相似的結構寫好幾遍,不方便管理,但實際運行效率卻極高。所以為了遊戲的優化,我們還是選擇了「面向數據」來作為該項目的編程核心思想與框架。

讀起來太晦澀了嗎?那實在不行的話我們就這樣吧!

不開玩笑了,回到正題

物理幀的大部分工作是由CPU來完成的,要維持60的幀率,一個物理幀允許的CPU處理時間不能超過16ms(毫秒),除開提交DrawCall渲染的時間和其他必須的開銷,只有大約11ms可用於一幀的遊戲核心邏輯。

單核遊戲?多核遊戲?都不是,這是一個GPU遊戲!

目前CPU的性能發展遇到了瓶頸,已經沒辦法再大規模提升單核性能,只能靠提升核心數量。而在很多實際應用的情況下,對核心數量的提升,遠不如增加一點點單核頻率提升的性能多。

雖然我們在星系的隨機生成及模擬、星球地形動態生成、無縫載入等邏輯中使用了多線程來緩解主線程的壓力,但是對於遊戲邏輯中如此龐大的計算量,就算有100個核火力全開多線程完美配合也未必駕馭得了!

從《戴森球計劃》的想法誕生之初,就決定了這是一個GPU遊戲。看那數萬顆太陽帆,每一顆的運動都遵循著萬有引力定律,每一顆都在計算髮電量,每一顆都能被近距離觀看。像大規模並行計算這樣的工作,使用GPU是不二的選擇。

我們將凡是可以並行計算的那部分計算工作,全部交給了GPU,剩下的那部分計算量,只要GPU能在16ms之內按時渲染出來,CPU就絕不會掉鏈子!

這同時也意味著,好的GPU的確能為《戴森球計劃》帶來更流暢的體驗,而CPU的影響則相對較小。

使用GPU來渲染大批量動畫

在現今主流遊戲引擎中,動畫大多是靠移動部件或骨骼的位置(Position)、旋轉(Rotation)、縮放(Scale)來完成的,如下圖:

該建築的動畫是靠旋轉移動部件來完成

就是這樣一個建築,它的動畫部件已超過50個,其中還包括父子Transform層級的嵌套,假設我們有1000個這樣的建築,那CPU需要同時處理的動畫子部件就有超過50000個,這顯然是CPU駕馭不了的,而這還僅僅只是建築動畫,並不是核心邏輯。

用CPU去逐一計算這50000個部件的Transform的確是相當不划算的,這些動畫其實可以並行計算,只要在畫面幀結束時,所有建築的動畫均就緒即可,這對於具有強大並行計算能力的GPU來說簡直就是小菜一碟。

我們在編輯器中將這個建築的所有動畫幀中所有的頂點位置、法線等信息按照一定的順序,事先錄製在一個VERTA文件中。

當遊戲載入時,只需要載入這些文件,通過ComputeBuffer將所有信息傳遞給GPU,這樣GPU就拿到了所有建築動畫的預烘焙信息,接下來再將每個建築的動畫狀態組成一個數組,傳給GPU。

圖:每個建築的動畫狀態數據

最後,還需要在vertex shader中分析這些數據,逐一還原每個建築在當前幀的建模。

圖:在vertex shader中還原當前幀建模部分代碼

按照這個思路,我們成功使用GPU Instancing還原了所有建築的動畫,還順便使用了建築狀態數據來控制建築貼圖上指示燈的開關。在動畫和建築狀態更新方面,CPU被完全解放。而在GPU中,僅僅只是多了150MB左右的顯存數據用於存儲所有建築的動畫數據(僅相當於幾張4096貼圖)與若干在vertex shader中的定址與插值計算。可以說是一頓免費的午餐了!

粒子特效

為了將特效渲染納入上面的框架中,所有的建築特效均無法使用引擎自帶的粒子特效,必須將原本是作為粒子來渲染的特效包含在模型網格中,再使用shader來逐一實現各個建築不同的特效需求。

圖:特效片元在製作時就包含在模型中

在遊戲中,幾乎每一個不同的建築都定製了不同的shader,對於同一個建築特效的不同片元,我們按照類別塗上不同的頂點色,哪些是輝光,哪些是要拉長的,哪些應該從下至上亮度遞增,通過不同的片元頂點色,就能做不同的處理。

圖:整個建築的動作與特效在一個shader中實現

需要時刻朝向太陽方向的建築,邏輯不能讓CPU來處理。我們將建築模型按照「底座」、「橫向轉動部分」、「俯仰轉動部分」塗上不同的頂點色加以區分,再在shader裡面計算這些頂點應該如何旋轉,從而朝向目標點。

圖:朝向太陽的shader代碼節選

有了這套機制,我們就只需要在主線程中計算好每個建築當前的狀態,形成ComputeBuffer,傳遞給GPU來進行統一渲染,在這個過程中,動畫、IK朝向、特效、自發光變化等等,就統統都有了。

Unity Profiler性能測試

說了這麼多,直接上目前的性能測試圖吧!

下面是100小時規模的存檔在Unity Profiler裡面的性能測試圖

開發機配置

從圖中可以看到,遊戲主邏輯物理幀CPU耗時5.11ms,也就是說理論上每秒可以跑到195個物理幀,所以CPU這邊肯定是沒問題,而最終畫面能跑多少幀,就看GPU的能力了,我的卡是660Ti,在暢玩了100小時後,還能跑上40幀,不過我們還將繼續不懈的優化,爭取將我這張卡的幀率提到60!

除了物理幀的優化以外,我們還非常看重C#的垃圾回收機制的優化,因為過多的內存垃圾會導致遊戲時常卡頓,嚴重影響遊戲體驗。

一般來講,每次觸發垃圾回收機制都會出現不同程度的卡頓,卡頓出現的頻率取決於GC Alloc的大小,而每次卡頓的時間取決於數據結構的複雜度。

為了儘可能消除遊戲卡頓現象,從立項開始,程序在數據結構上就嚴格把控,能用數組的地方用數組,盡量少的使用Dictionary或List,凡是物理幀的邏輯除數組擴容等操作以外,均不能產生GC Alloc,在UI邏輯中嚴格控制字元串的操作,避免不必要的開銷。

據測試,目前遊戲的GC.Collect卡頓時間已控制在30ms以內,出現頻率為幾乎沒有。

下圖為100小時規模下的GC性能統計:

遊戲主邏輯在物理幀上的GC Alloc為0,只有UI上有132位元組的開銷,加上一些引擎必要的開銷,每幀總的GC Alloc為5.0KB,目前這個數值處於非常低的水平。

以後如果有時間的話,我們會介紹物流運輸機、戴森雲的優化,看看GPU是如何輕鬆達到「數十萬」這個數量級!


物理幀的大部分工作是由CPU來完成的,要維持60的幀率,一個物理幀允許的CPU處理時間不能超過16ms(毫秒),除開提交DrawCall渲染的時間和其他必須的開銷,只有大約11ms可用於一幀的遊戲核心邏輯。

單核遊戲?多核遊戲?都不是,這是一個GPU遊戲!目前CPU的性能發展遇到了瓶頸,已經沒辦法再大規模提升單核性能,只能靠提升核心數量。而在很多實際應用的情況下,對核心數量的提升,遠不如增加一點點單核頻率提升的性能多。雖然我們在星系的隨機生成及模擬、星球地形動態生成、無縫載入等邏輯中使用了多線程來緩解主線程的壓力,但是對於遊戲邏輯中如此龐大的計算量,就算有100個核火力全開多線程完美配合也未必駕馭得了! 從《戴森球計劃》的想法誕生之初,就決定了這是一個GPU遊戲。看那數萬顆太陽帆,每一顆的運動都遵循著萬有引力定律,每一顆都在計算髮電量,每一顆都能被近距離觀看。像大規模並行計算這樣的工作,使用GPU是不二的選擇。我們將凡是可以並行計算的那部分計算工作,全部交給了GPU,剩下的那部分計算量,只要GPU能在16ms之內按時渲染出來,CPU就絕不會掉鏈子!

無獨有偶,在計算化學領域,有一種叫分子模擬的計算方法,同樣是由於使用了GPU處理大規模並行計算而出現了革命性的突破,相同的分子模擬任務,使用GPU計算幾乎可以得到比CPU任務快出幾個數量級的差異。這樣的進步使得分子模擬出現了革命性的突破,我們從之前的只能模擬小分子,小體系的皮秒納秒級行為變成了可以模擬大蛋白甚至是蛋白複合物的微秒甚至毫秒級的變化;

新冠病毒刺突蛋白識別人類ACE2細胞受體的動態過程

在我剛接觸這方面的時候,也有想到用同樣的方法來處理這種開放式世界遊戲的世界演化想必同樣是革命性的突破,然而以我的水平肯定是做不出這樣的突破的,不過幸運的是,沒過多久,作為玩家的我就有幸看到了戴森球計劃——在遊戲領域有牛人把GPU的並行計算能力應用了起來,看到這個消息的時候我欽佩不已,情不自禁高呼666並趕緊入手了一波~

連遊戲的開發者都情不自禁自問自答了一波給自己打call哈哈;

於是,我們就看到了地表與太空的無縫切換,實現了真正的3D開放世界而不必受限於電腦配置而講遊戲變為2D平面上的遊戲,這使得整個遊戲給了玩家一種無與倫比的沉浸感,你甚至能感受到巨行星鋪面而來的窒息和從黑洞旁掠過的震撼(觀光遊戲實錘),更令人震驚的是,如此震撼的效果居然是一個辦公用筆記本電腦可以流暢帶的起來的……這大概就是GPU的魅力吧

關掉天體標註沉浸感會更強

親眼看到自己研究中有了解過的技術被應用到遊戲上,不禁有那麼億絲絲激動哈哈哈

希望有更多在學術界和工業界叱吒風雲的硬體和技術能應用到我們的生活中來!


看過一篇對開發團隊專訪的文章,提到在項目立項初期,團隊就已經把遊戲整體的開發計劃都列好了

其實我們開發《戴森球》真沒走過什麼彎路。在項目開始之前,我們就已經確定好了關於系統、玩法的所有策劃。每個內容需要什麼技術多少工期,每個星球需要多少種植被,每個建築需要多久時間建模,還有遊戲需要多少動畫,多少特效......這些都是正式立項之前就完整排列好了的。」

BB姬:被老外吹爆、登頂全球熱銷的國產遊戲《戴森球計劃》是怎麼做出來的??

zhuanlan.zhihu.com圖標

因為前期規劃充分,後面整個開發流程就是按部就班、行雲流水,沒有那些所謂的方向變更,臨時需求,推到重做,甚至開發過程中遇到的各種技術難題都是提前預料到的

他們五人團隊的這種策劃能力、執行能力,真的是可以吊打國內某些所謂的遊戲大廠團隊了


樓上的我懷疑你在自問自答,不過我想點贊


cpu單核能力有限,而且幾乎沒有提升了。

多核呢又難做,效果也一般。

GPU才是未來,並行能力max,有多少性能就有多少提升。


這個技術真的太強了,我筆記本集顯玩雖然幀數低,但是開局的幀數和造了無數傳送帶建築以後的幀數沒有變化。

想之前玩gmod社區伺服器,服規里寫明了用槍不能連發,不能建造太多東西,不然就卡爆了。太強了


推薦閱讀:
相关文章