祖龍技術總監王遠明:用虛幻引擎解決開放世界5大難題

遊資網發表於2020-11-30
11月27日,由Epic Games舉辦的2020年虛幻引擎技術開發日大會正式拉開帷幕。會上,祖龍娛樂的引擎技術研究總監王遠明帶來了“厚積薄發,祖龍娛樂使用UE研發開放大世界的實踐”的主題演講。

祖龍技術總監王遠明:用虛幻引擎解決開放世界5大難題

以下為演講內容(有節選):

一個好玩的遊戲是具有一個超大的世界,這樣的超大的世界它會給玩家帶來無與倫比的真實體驗,開發一這樣的大世界的遊戲需要哪些挑戰呢?

首先我們先講一些優化內容,主要是效能和記憶體。然後再給大家講解一下開發迭代的過程,這其中包括一些工具。

祖龍技術總監王遠明:用虛幻引擎解決開放世界5大難題

超大世界的MMORPG它有很多的優勢,首先它會有更加真實的遊戲體驗,因為我們平時玩的遊戲如果是場景比較小的話,它會有一個頻繁的載入和解除安裝的過程,並且它也不符合我們在真實世界中的生活體驗。

我們講的大世界,它不管是視距也好,減少loading的這種頻率也好,它會給玩家都是一種非常真實的體驗。並且在減少loading的情況下,它會讓策劃有很大的空間來設計更加豐富的遊戲玩法。

祖龍技術總監王遠明:用虛幻引擎解決開放世界5大難題

如果要做一款開放大世界的遊戲,會面臨哪些問題?

大世界需要解決一些很實際的問題。

祖龍技術總監王遠明:用虛幻引擎解決開放世界5大難題

場景

首先是場景的建立編輯。因為大世界不同於小的世界。小的世界你可以用美術手工去拉地形、刷紋理、鋪植被,這些方式都可以解決。但是大世界它的工作量非常會非常大,並且它的這種對真實感的要求的也非常高。如果還採用原始的那種美術去拉地形、刷紋理的方式是非常地低效,並且不會帶來很真實的體驗。

並且還帶來一個問題是大的世界我們一般採用分塊的方式來做,這就會有一個問題是多人協同。像以前每一個場景是一個獨立的場景,由美術的不同的人員來做的話,他們彼此之間的工作是一個獨立的,不會存在有交集。但是大世界的不同的分塊它是有這個相連的關係。這樣就要求我們不管是工具上來講經常來講都要處理好接縫的問題。

光照

還有就是光照問題。小的場景,光照資料比較小,它的光照烘焙的這種方式也比較簡單。單獨的一個場景載入下來,幾天之後就可以做一個LightingMap的烘焙。

那大型的場景,由於分成不同的區域,它這樣的方式就會產生一些問題。比如說同樣的一棵樹,它可能會投影投到相鄰的兩個或者是三個或者更多的場景塊。這就需要在烘焙單一的地形地塊的時候,做一些額外的特殊的處理。

場景迭代

還帶來了一個問題就是我們怎麼樣去進行一個迭代開發,怎麼樣進行二次編輯。還是一樣,如果一個小的場景,迭代是一個非常簡單的事情,因為它不影響其他的場景。

對於大場景的分塊來講,如果編輯之後需要二次修改的話,怎麼樣去解決一個工作流,怎麼樣去方便地更新,怎麼樣能夠使最終遊戲的配置包儘可能地小,這也是一個需要解決的問題。

還有大的場景會帶來大植被的這樣一個功能需求。因為你場景比較大,如果你的植被範圍比較小的話,它也是不是很真實的。這也是需要我們解決的就是如何建立和渲染出高範圍大範圍的這樣一個植被。

大的場景的遊戲還需要解決一個問題,就是我們的場景的實時的載入和解除安裝。它不像小遊戲,小遊戲當你進入一個關卡的時候,它的整個場景是全部載入完成的。因為會走一個進度條。當載入完成之後,你在遊戲裡不管打怪、做任務、還是聊天已經不涉及到場景的載入了。

祖龍技術總監王遠明:用虛幻引擎解決開放世界5大難題

相反換成大場景以後它會遇到一個問題,是玩家在運動過程中,會涉及到場景的載入和解除安裝,載入量是非常地巨大,這樣會造成一些卡頓。並且當在載入特效或者是別的模型的時候,可能會出現一個載入不及時的問題。

貼圖

貼圖的問題也是,因為記憶體變大了,你的模型、貼圖、地塊,這些都非常佔記憶體。

執行效率

還有執行效率問題。場景大了之後,為了營造出一個逼真的感觀,你的視野會必須要放得無限,不能說把這個遠處的這種輪廓,通過一個視距的Culling把它裁剪掉。這樣的話會有問題,當人物向前跑動的時候,你的遠處的地形會變形,逐漸的進入到遠平面以內,這樣的話你會產生一個錯覺是那種遠處的山好像在慢慢生長出來,這樣對於遊戲的體驗會非常的糟糕。

另外極大解決的問題就是我們的執行效率。因為大場景意味著大的模型數量、大的面數,以及帶來的很多高數量的DrawCall和CPU的消耗,場景管理的邏輯會變得更加的複雜。並且模型多了以後,它的Tick,每幀需要處理的邏輯也會變多,這也是一個CPU需要解決的問題。

5種方式解決製作難點

接下來我為大家逐一地介紹我們的這個大世介面對這些問題的解決方案!

建立真實場景

首先我們怎樣去建立一個真實場景。之前小場景是通過美術去通過畫刷去拉出地形,然後通過一些隨機數的擾動來模擬出來一個凹凸不平的地形。這種真實感是非常地不足的。我們現在採用的是Houdini的這樣一個軟體工具來建立真實的地貌。

Houdini這個工具其實是一個非常強大的工具,它是基於一個節點模式工作的。也就是說它的所有修改都是一個節點。這個節點可以序列化並行化來操作,經過層層的節點的不斷地計算,呈現出一個最終的形態。

第二個它是所有的操作也好,模型地形也好,都是通過副檔名為Hda的檔案來儲存的。我們在這個的解決方案當中,我們所有的操作都是基於建立一個一個的Hda的的檔案。

比如說我們去建立地形的某一個地表的操作都是建立成為一個一個的Hda檔案,我們在用Houdini建立出大世界之後,最終的目的是要把它在整個遊戲場景裡分拆成很多的小塊,這樣的話我們才能做到逐一地載入,然後逐一地解除安裝。這樣的話就有一個大世界的拆分建立和拆分,這也是我們需要重點去解決的一個問題。

解決邊界融合

有了分塊之後,我們需要的解決方案中就包含了分塊地載入和每一塊的單獨的編輯。當我們單獨編輯每一塊的時候,並且多人協同的時候,我們會發現不同的相連的塊有可能會被不同的美術去編輯,這就遇到一個邊界融合的問題。

我們也提出了一個相應的解決方案,還有很多物件是跨很多分塊的。比如說道路、河流這些它是比較蜿蜒曲折很長的,這就要求我們有一種方法能夠對這種跨塊的這種物件進行一個編輯,這也是我接下來將要提到的我們是怎麼去解決這些問題。

真實的場景不光是需要地形地貌來體現出真實,它還必須要有一套比較完善的真實地貌系統。我們改進了UE的植被系統,可以和Houdini來結合來生成最終地表上的植被系統。這也幫助了我們節省記憶體,節省DrawCall,以及提高渲染效率。

處理場景迭代與工作流

編輯好場景釋出之後,接下來我們會介紹我們場景迭代的解決方案,其中也會介紹我們的工作流。

大世界分塊了之後,它並不是靜態的,它必須是由動態的載入機制載入到遊戲裡面才能夠被玩家所看到,才能夠被玩家所接納。對於大世界的一個很重要的因素是視距要無限的遠。

在這種情況下,我們怎麼去設計載入機制呢?一般我們需要載入不同的LOD,因為我們要涉及到記憶體的節省。我們在這個遠處的地方是載入這個最差一級的LOD,拿這個和在較近的地方,精度比較稍微低一點的地形塊進行比較。在最近的地方我們是載入全精度的,然後我們實現的是一套全Lua,實現的一個載入邏輯。我們並不會使用World Composition這樣的一個引擎自帶的載入邏輯。

提升執行效率

相對於小的遊戲場景來講,這個問題倒不是特別突出。當場景大了之後載入的多了我們的DrawCall數量就會多。因為你載入了很多這樣的分塊,這些分塊都有一些東西是要為豐富這個場景服務的,它的DrawCall會很多,我們主要採用了Hierarchical Instance的方式。

每一個分塊裡面,最多有一種型別的Hierarchical Instance,這樣的話我們就保證了以這種方式渲染的物體,一個分塊只貢獻一個DrawCa,對於較遠處的小物體部分的低精度的物體,我們是不投射陰影的。另外我們會分類別設定不同的Culling Distance。

採用動靜結合的光照設計

我們光照的解決方案,是採用了動靜結合的方式。

有一些遊戲可能也是大場景,但是它是採用了全動態,但這方面我們是考慮到了執行的消耗,因為我們想為玩家儘量地建立一個比較真實的遊戲體驗。

比如說樹這一物體,在遠處的假山、石塊都會有很多,採用全動態的光照系統可能造成DrawCall扛不住,所以我們採用的是動靜結合的光照方式。在遠處我們可以採用完全的ShadowMap,在近處採用動態陰影。因為我們沒有采用LightingMap的方式,所以我們的場景在戶外其實是沒有的。

具體實操過程

剛才粗略地列舉了一下我們的一些解決方案,下面我們會重點介紹一些解決方案具體的實施的過程。

分塊載入與編輯

分塊載入和編輯,我們剛剛說了。最終的Tile.hda是我們的最小編輯單元和最小載入單元,Tile.hda拆分以後,將會對應上UE的level,在這個level裡面有一個叫做UHoulandProxy這個Actor,它是作為一個UE物件和這個Hda共同互動的一個橋樑。

在它的Proxy身上,我們會利用Houdini的各種外掛提供的API來編輯。當前Tile.hda這個檔案編輯好了之後,我們通過Houdini的API產生的程式化資料來重新整理UE的地形,然後通過UE引擎將地形地貌渲染出來。

祖龍技術總監王遠明:用虛幻引擎解決開放世界5大難題

需要注意的是,每次的編輯依然是以節點的方式儲存修改,每一個節點是一個以Hda檔案的形式儲存的。一個Houdini的檔案在這個Level裡按常規的方式編輯Level裡的其他物件。

比如說我們需要在這個場景裡放一個建築,放一個光源,然後再放一些策劃們需要的一些東西,我們是採用常規的UE的編輯器來編輯。而地形地貌則採用Houdini的方式編輯。

值得注意的是,邊界融合的編輯。

祖龍技術總監王遠明:用虛幻引擎解決開放世界5大難題

圖中綠色的邊界,右邊的圖是做了一個高度的調整,也做了一個紋理的漸變,所以它看起來就比較真實的。

祖龍技術總監王遠明:用虛幻引擎解決開放世界5大難題

場景迭代的具體處理

在釋出之後,我們肯定還是需要對場景做一個修改的,就涉及到剛才說的場景迭代的過程。

在迭代的時候,我們儘量不要修改,整個世界的地貌。因為如果你整個世界的地貌修改了就是說修改了大世界,就要涉及到Tile.hda的重新批分、批拆,然後被拆成不同的Area最後再拆成不同的Tile,整個的工作流就會很長,它的影響面也會比較大。

祖龍技術總監王遠明:用虛幻引擎解決開放世界5大難題

不過如果確實有修改需要的話,我們的這種供應鏈是可以支援的。因為修改完了之後,在最終的Tile.hda編輯時,所生成的節點都是基於這個操作的,我們最終在場景迭代的時候,對大世界的地貌、地形的修改,其實也是可以最終反映到最終的Tile.hda上去的。所以這也是我們使用節點的方式操作,而不是儲存最終修改狀態值的,達到省LOD的作用。

光照設計的完整方法

光照的解決方案,剛才介紹過了。具體實施過程,我們對光照主要是採用靜態的ShadowMap、以及動態光照的方式,因為完全的動態,光照有比較多的DrawCall,我們為了追求真實的這種大場景,可能會承受不了。所以只能是在遠處部分採用靜態的ShadowMap。

而角色是動態的陰影,這裡我們只使用ShadowMap,不使用LightingMap,所以我們是沒有建立光照資訊資料。

我們還要儘量減少動態點光源的數量。由於我們在遊戲的過程中,我們會實時地載入分塊,這樣的話會造成一定的卡頓。不像小場景,我們是預先載入了所有的整個場景的,所以小場景的這種實時載入的工作量是比較小的。

而大世界不一樣。首先我們沒有辦法做預先載入過多的內容,因為我們本身場景的內容已經非常多了。同時我們也沒有辦法做太多的Preload的內容,這就意味著需要儘量去讓更多內容是實時載入的。

但是如果我們全部場景內容都採用實時同步載入的話,這個卡頓的情況會非常的嚴重。所以我們採用了非同步的載入方式,即需要哪個就載入哪個,節省記憶體,解決卡頓的問題。

節省記憶體

大世界還帶來一個問題是記憶體壓力變大,因為有很多的貼圖,很多的靜態模型,載入的塊太多了。並且我們為了達到無限的視距,至少所有的塊都要載入進來,還得是載入一個LOD這樣的精度,造成我們的記憶體壓力很大。

所以我們要做一個Mipmap的剔除,這是我們自己加入的功能,以此減少我們模型的種類。

祖龍技術總監王遠明:用虛幻引擎解決開放世界5大難題

貼圖的記憶體佔用量是非常大的,當我們做了一個Mipmap的剔除之後,我們的記憶體會得到很大的改善。

還有將資源的分級。涉及到不同的StreamingLevel對記憶體影響大的,我們可能走StreamingLevel的量要多一些,而對於記憶體影響少的我們就可能少些。

精度比較低的StreamingLevel我們就不載入了,能夠達到省記憶體的作用。還有就是每一個分塊做不同的LOD級別。然後通過改變我們的載入距離,當記憶體小的時候,我們應該載入LOD的就載入LOD,這樣的話最終也能起到節省記憶體的作用。

今天的分享就到這裡。希望以後,更多地跟大家交流。謝謝大家!

來源:遊戲陀螺
地址:https://mp.weixin.qq.com/s/wdEWX8wC8zmNxG5Y-SXLgw


相關文章