Unity的超大開放世界解決方案

刘伟贤發表於2019-12-27
近期,Unity在北京、成都、深圳分別舉辦了三場製作人專場活動,搭建優秀遊戲製作人與Unity官方面對面交流的橋樑,內容涵蓋專案最佳化、技術美術與解決方案等多個方面。

本文為大家帶來的是Unity技術支援工程師劉偉賢的演講-《Unity的超大開放世界解決方案》。你可以點選[閱讀原文]下載本次演講的PPT。

下面是本次演講影片。


演講內容

大家好,很高興這麼多人在場聆聽,首先簡單介紹一下我自己。

我是劉偉賢,是Unity在廣州的技術支援工程師,主要負責企業級技術支援的工作,服務過很多企業客戶。

Unity的超大開放世界解決方案

今天,我為大家帶來的演講是《Unity的超大開放世界解決方案》,在座的不少人是開發移動端遊戲的,所以我的演講內容將著重面向移動端的解決方案。

首先,向大家介紹一下我分享這個專案立項時候的一些情況。

Unity的超大開放世界解決方案

立專案標是使用當時比較新的Unity 2019.1版本,遊戲型別類似《絕地求生》,遊戲具有長視距和開放世界的元素。

我們設定攝像機為自由視角或鎖定第三人稱視角等。對於其它型別的攝像機,我們在有需要的時候也會嘗試一些實現。

關於目標裝置,我們主要面向是三星Galaxy S9和iPhone 8及以上的裝置。遊戲執行的目標幀率是30幀。

對於移動端,我們選擇使用的是輕量級渲染管線LWRP,但是實際上我們也實現了基於高畫質晰渲染管線HDRP。所以整個大世界的解決方案,我們已經覆蓋了LWRP和HDRP。(小提示:LWRP目前已改名為通用渲染管線URP)

為了保證客戶可以更好地接入這個方案,絕大部分指令碼的實現都是基於C# source package,也就意味著大家可以即插即用,非常簡單。

遊戲世界大小方面,我們是最小以4K×4K的世界。關於表現相關的部分,我們覺得風格化的也可以,但是暫時還沒有做更多照片級的真實渲染,我們也藉助了一些外部的工具來完善整體的流程。

總體來講,整個超大世界的方案中,我們有下面的這些功能。

Unity的超大開放世界解決方案

首先是使用HLOD System + Terrain HLOD System,可以替代很多靜態的Mesh網格,把它們進行合批和減面,達到一個在長視距的時候能夠有比較好的記憶體和效能的指標。

關於Shadow Map陰影貼圖,我們使用內部最新的Voxelized Shadow Map,它基於稀疏體素八叉樹的演算法,可以轉換高解析度的Shadow Maps陰影貼圖。

在美術和設計的工具方面,我們採用了Houdini,來配合Unity做一個超大世界的地形的生成。例如:道路、樹木、橋樑、石頭的生成等。

Streaming流式載入是基於我們的HLOD System,裡面會涵蓋到我們的預製件、紋理、網格等。我們選用較新的Unity 2019.1這個版本的時候,也是考慮了Texture Streaming紋理流式載入等這些引擎後面提供的新功能。

還有Occlusion Culling Streaming,因為對於一個超大世界來講,如果想要提高剔除效率的話,可以利用Occlusion Culling提前進行跟遮擋相關的剔除。對於超大世界而言,可能烘焙下來的離線資料量比較大,所以我們提供了Streaming的方式去做流式載入。

Light Probe Layout Tool和Light Probe Streaming是跟我們Lighting Occlusion光照剔除相關的工具,主要功能是自動化地排布Light Probe光照探針,並且在製作超大世界的時候,我們對光照探針做了一個Streaming的工具。

最後是Indirect Draw,簡單來說就是充分利用CPU的資源去做Culling剔除、Indirect Instancing之類的操作。

下圖左邊的一二列跟上一頁是一樣的,我希望大家可以瞭解一下右邊的列,這是相容性方面的內容。

Unity的超大開放世界解決方案

對於Unity 2019.1之前的一些版本,例如:Unity 5.6的版本,可能要了解這部分。但在Unity 2019.1之前的一些版本中,有一些HLOD System是可以相容的,但Voxelized是沒有辦法相容的,因為這在引擎中做了一些改動。

Houdini + Unity的流程是可以使用的。

基於HLOD System的Streaming流式載入,因為它是基於Addressable Asset的,所以在Unity 2019之前的版本,可能要自己實現基於Asset Bundle的Streamer。

這裡有一點小改動,Occlusion Culling也是可以相容的,Light Probe Layout Tool和Light Streaming的相容都是完全沒問題的。

Indirect Draw方面,目前無法支援我們的渲染管線。

Unity的超大開放世界解決方案

對於整體的Solution Item解決方案部分,我會按開發的流程去講:首先是如何得到這個場景,得到這個場景之後,如何把這個超大場景管理起來,場景管理起來以後,Lighting Solution光照解決方案是怎麼樣,如何處理光照和影子等。

Unity的超大開放世界解決方案

然後,我們還要處理場景裡面很多地表上細節的物體,下面我會詳細講解一下。

首先是Houdini + Unity Workflow工作流程。因為我是技術人員出身,所以對於美術相關的事情,更多地會去求助技術美術或其他的技術同事。

Unity的超大開放世界解決方案

在開發超大世界的時候,很難有很多人員去參與超大世界的搭建,所以我們需要使用Houdini去生成地形,能夠有路、有河、有橋等。生成完之後,匯入到Unity中,就可以很方便地在Unity裡面對這些引數進行調整。

當我們把這些東西都調整好,得到一個超大場景的時候,我們就可以進入到HLOD System進行預處理的狀態。當到HLOD System預處理完了之後,我們就可以得到在觀看時真正去執行的狀態。

藉助Houdini,我們可以快速進行Demo驗證階段和技術驗證階段,很快得到比較方便的模型。

下面介紹HLOD System對於場景的管理。

Unity的超大開放世界解決方案

首先,HLOD System主要的目標是為了減少Draw Call。然後,進行更多的Batch批處理,

其次,減少面數和紋理,來使用不同的LOD Level。這些Draw Call減少、Batch提升以後,我們也對面數貼圖和材質做了減法,這樣我們相應地節省了記憶體,並提升了載入時間。

目前,HLOD System只針對當前所在的地方進行載入,它會流式載入網格和紋理,在後臺進行非同步的操作。

大家可能會問:HLOD System和原來使用的LOD有什麼差別?

如下圖所示,這是HLOD System和LOD的對比圖。

Unity的超大開放世界解決方案

HLOD System和LOD兩者有一個共同的特性是:都可以做一些減面的操作。

當我們把面數減下來之後,LOD不能減少Draw Call和Memory Usage,也就是不能減少記憶體,LOD也不能提升CPU的開銷,特別是在Culling和LOD的計算上。所以我們開發全新HLOD System來彌補這些方面的不足。

下圖可以直觀的展示LOD System和HLOD System兩者之間的差別。

Unity的超大開放世界解決方案

例如:最左邊的圖是最終效果,如果我們能看Draw Call的話,就算我們用不同的LOD等級,可能它的Draw Call都像中間這張圖一樣,它會需要很多Draw Call來把場景畫出來。使用HLOD System以後,它可以最終只使用一個Draw Call來把場景畫完。

下圖是我們開發HLOD System時的一個測試場景,這裡的Batch數量原來有5642個。

Unity的超大開放世界解決方案

如下圖所示,在我們使用HLOD System後,Batch就變成了952個。

Unity的超大開放世界解決方案

下圖是效能上的對比情況,使用HLOD System後,Draw Call從5642個降到了952個,佔比降到了原來的16.87%。三角面數也從原來的8M降低到3.9M,是原來的50%左右。

Unity的超大開放世界解決方案

HLOD System整體的流程是怎樣的呢?

如下圖所示,我們最開始從Houdini匯入了一個場景到Unity,我們會在Unity轉換為遊戲物件,然後再得到預製件,這時候我們會進入到HLOD System,HLOD System其實最重要主要有四個階段。

Unity的超大開放世界解決方案

首先是Splitter階段,我們要把巢狀預製件根據樹型結構進行切分。

切分之後,Simplifier階段會去做減面的操作,我們會根據不同的Leaf葉子節點,來判斷這是較高等級的節點,還是較低等級的節點,來進行減面的操作。

當我們根據不同的LOD等級進行減法之後,我們進入Batcher階段進行合批處理,對低等級的根節點進行合批的操作。

最後是Streamer階段,我們會把它匯出為預製件,透過Addressable Asset進行Streaming的操作。

這也是為什麼經過HLOD System以後,我們可以把Draw Call合批到一起的原因:我們對整個場景進行了樹型結構的整理、檢驗和批合,最後透過Streamer階段進行流式載入。

Unity的超大開放世界解決方案

在Runtime執行時的時候,HLOD System要做的事情就比較簡單。因為我們大量的工作都已經在預處理階段處理好,所以在執行時的時候,我們只要在Camera PreCull的時候,進入HLOD System更新Culling的資料,選擇要顯示的是低精度的節點,還是高精度的節點,還是把它隱藏掉。

這跟原來LOD System有很大的差別。如果使用過原來的LOD Group的話,雖然LOD可能分成了很多等級,但裡面的網格其實已經進入記憶體了,只節省了渲染的開銷,依然無法控制Culling。

HLOD System會從根源上解決很多問題,它可以精準地把需要的內容渲染出來。

建立超大世界,有一個很大的難題:Lighting Solution,也就是光照方面的問題。

Unity的超大開放世界解決方案

目前Unity內部採取的是LightProbe baking + VSM(Voxelized Shadow Maps))+ CSM(Cascaded Shadow Map)的解決方案。

VSM體素化陰影貼圖是給長距離大範圍的空間使用。對於近距離的物體,我們還是使用原來的CSM級聯陰影,來達到更好的精度。對於遠近景物的融合,我們希望可以達到比較協調的狀態。

Voxelized Shadow Map體素化陰影貼圖的工作流程非常簡單,我們會在離線時做資料的處理,也就是基於稀疏的八叉樹的體素化演算法來離線處理資料,生成高精度的陰影貼圖。

Unity的超大開放世界解決方案

在執行時,這跟原來沒有太大的區別,但是中間有一步是Screen Space Shadow Compute Pass,這裡我們會使用Compute Pass進行一些跟計算相關的事情。

Unity的超大開放世界解決方案

下面是一個效果圖,包含了靜態物品和動態物品融合的狀況。

Unity的超大開放世界解決方案

我們可以看到Voxelized Shadow Map體素化陰影貼圖,在不同的解析度下的構建時間和佔用記憶體的大小。這是展開的大小,因為對高體來說,其實還可以進行資料的壓縮,來降低這部分資料。16K指的是解析度。

下圖是將VxShadows放到HDRP裡面,進行體素光照的展示。

Unity的超大開放世界解決方案

剛才講到了關於陰影的部分,除了陰影以外,還有漸進光相關的一些事情。我們在這主要靠光照探針的貢獻。

如果大家用過光照探針的話,就知道對光照探針最麻煩的事情是要手動去布點,往往在光源變化比較大的地方進行手動密集布點。但是這樣做的話很累,因為需要不停地布點、修改和Bake烘焙。所以我們提供了兩個工具:LightProbe Auto Layout Tool和LightProbe Streaming。

Unity的超大開放世界解決方案

LightProbe Auto Layout Tool提供了方便的方式,來生成大量的光照探針,替代人工放置的操作。

LightProbe Streaming會把光照探針資料切分為不同的區域部分,在執行時進行流式載入,確保不需要把大世界的光照探針資料都放到記憶體裡面。

下圖是LightProbe Auto Layout Tool工具的截圖。這個工具是我開發的,左邊的圖是其中一個樣式,我們可以點一下按鈕,讓它自動生成光照探針的排布。

Unity的超大開放世界解決方案

LightProbe Auto Layout Tool有非常簡單的工作流程,首先它提供一些Generator,這些Generator是排布的規則,裡面提供了五種排布的規則。

Unity的超大開放世界解決方案

第一種是基於網格,按照AABB一個個點來排布。

第二種是對於沒有LOD等級的網格,對網格進行包圍的計算,它有一定精度的數值,控制光照探針如何精準地包圍產品的物件。

第三種是基於LOD Group Mesh的Generator,在排布光照探針時,我們會基於哪一級的LOD來進行排布。

第四種基於Light的Generator,它可以在光源變化的地方,比較密集地排布光照探針。經過我的試用,這種方式非常好用。

第五種是基於Terrain地形的Generator,在Unity 2019.2中,我們的光照探針已經支援讓靜態物體和動態物體同時受到光照探針的影響,所以使用光照探針做這樣的方案是沒有問題的。

這幾個Generator可以組合使用,並不是只能單獨使用其中某一個。

當排布好光照探針之後,我們會提供Optimize Baker。在烘焙的過程中,我們不需要生成Lightmap光照貼圖,我們只需要把間接光這類低精度資訊烘焙到光照探針就可以了。所以我會提供最佳化後的Baker,來把光照探針烘焙出來。

烘焙完成後,我們會提供專門用來做最佳化的Optimizer。畢竟這些是自動化排布的探針,而且是組合使用的結果,所以難免會產生一些小問題,例如:光照探針之間非常接近,光照探針在物體裡或地底下。

因此,我們提供了Optimizer來進行光照探針的裁減,把烘焙完的差異較小的探針剔除掉,並且把全黑的光照探針也剔除掉,最終達到的效果是:有比較合理的光照探針存在場景中。

最後一步是進行切分,然後進行流式載入。

剛剛說完了我們的Lighting Solution光照解決方案,現在講一下場景裡面的細節物體。在遊戲裡面,細節基本上是大家非常熟悉石頭、樹、草、植被等。

Unity的超大開放世界解決方案

對於Render System渲染系統,我們最主要做的兩件事情:第一件是使用GPU去做世界的Culling剔除,第二件是使用Indirect Instance Draw把細節畫出來。

聽起來似乎很簡單,但是實際上在系統裡面,我們加入了四叉樹,在傳遞到GPU之前,我們還會進行簡單的裁剪,以及針對樹的最佳化。如果我們把每棵小樹作為個體,這個資料量還是蠻大的。因此,我們後續還有調整的方案。

關於Occlusion Culling Streaming,我們沿用了原有的Occlusion Culling遮蔽剔除功能,然後我們給它加上了Streaming流式載入的功能,基本上,它是對烘焙好的Occlusion Culling資料進行Streaming的操作。

對於未來Roadmap路線的話,我們的研發人員還在開發一些新的功能。

Unity的超大開放世界解決方案

例如:使用Virtual Texture對超大場景的地形進行支援,然後Terrain System地形系統也有全新的基於Clipmap的系統。

在光照探針這塊,研發人員也在進行對Light Probe Data光照探針資料進行重新編碼,把資料存在一張紋理裡面,使其得到更高的精度。畢竟從光照探針到光照貼圖的精度差異是有點大的,所以我們使用折中的方案來提升這方面的精度。

下面給大家看一下目前我們基於HDRP的技術Demo。


大家可以看到下面還有一些紅色的技術報錯資訊,因為這些內容還在開發階段。Demo裡的素材可能看起來不是很炫酷,但它只是一個技術的驗證。

這是目前我們在製作的技術Demo,把整個大世界放到HDRP裡面,其實整體技術方案對LWRP和HDRP來說,基本上全都適用。目前我們用的版本是Unity 2019.1.7f1。

除此以外,其實我們也給其它行業做了跟大世界相關的事情,例如:這是我們做的智慧城市,這也是偏技術Demo的內容,裡面包括:建築物、道路、樹木等等。

目前,我們這一套大世界的方案,除了我們跟很多客戶在合作以外,在其它一些行業和領域都有使用場景。

我今天的分享就到這裡,謝謝大家。

作者:劉偉賢
來源:Unity官方平臺
原地址:https://mp.weixin.qq.com/s/4h_DrYLdvGLUtWKzsdt8QQ

相關文章