Generate Navigation Mesh with World Composition


簡介


使用先前提供的做法,把現實世界的地形檔匯入UE4之後,
畫面表現正常了,地圖也會根據設定的streaming distance運作。
下一個目標就是讓AI角色能在這塊地形正常的跨區域移動。

但是我很快就遇到兩個問題
1. 在play in editor遇到新的地圖載入的時候卡頓。
2. Navigation mesh要build 超久

首先是我在play in editor內,只要遇到地圖檔讀取就會造成卡頓,
但是我的地圖檔除了地形跟navigation mesh之外沒有放置其他的物件。

再來就是在build navigation mesh的時候超級慢,Build一張要5分鐘以上。
並且會伴隨很多的warning。

我做了不少的實驗想要嘗試改善這些問題,但是最後都是失敗的。例如:

降低地形複雜度


一開始我有嘗試用Flatten tool把地形輾平,也沒有加快Build path的速度。
代表地形的複雜度不影響build path以及loading的速度(或是差異不夠大)。

維持分割地圖數,降低height map解析度


將每一張tiled height map解析度輸出的時候從2017*2017降為505*505,
沒有差很多,但是地形大小不一樣了,不符合我的實驗。
效能改善的基本重點,當然是希望輸入輸出儘可能一樣,改了就不對了。

維持總解析度幾乎一致,分割地圖數變多。


例如原來是一張大地圖檔輸出成4*4張tiled map(2017*2017)。
改為一張大地圖檔輸出成9*9張tiled map(505*505)。

可想而知,每一張地圖都變小了,應該可以有效增加解析度,
但是原來只要build 16個level的navigation mesh。
現在變成要build 81次...

手動操作一兩張地圖測試後,確定是可以降低讀取時間。
不過以人工來說過於費時。需要靠程式批次處理。

因為navigaion mesh存在各個子地圖會增加地圖檔大小,有可能讀取卡頓問題也跟資源變大有關。

最後發現UE4提供不少產生navigation mesh的用法,於是研究一下各種方法的優缺點,或許可以解決讀取問題。

這是本系列的第三篇
目前一共有以下幾篇為系列的文章

1. Import RealWorld Landscape to UE4

2. 了解Landscape的組成元件

3. Generate Navigation Mesh with World Composition

4. Build Static Navigation Mesh in World Composition

Navigation Mesh in World Composition.


Unreal總共有以下幾種Navigation的使用方法,以下列出詳細的操作步驟。

產生Navigation Mesh的操作流程

1. Static NavMesh

通常用在關卡式的地圖,一個關卡就設置一個Navigation Bounds Volume(以下簡稱NBV)
整個NBV就是罩住整個場景,然後在Editor點選Build Path,儲存有NBV的地圖,這樣就完成了。
2. Static NavMesh with World Composition

在文章中有提到使用World Composition也可以讀取static NavMesh。做法如下:
1. 在主地圖放置一個NBV,可以不用罩住任何東西。
2. 自動產生於主地圖的RecastNavMesh-Default內,有個屬性Runtime Generation設為Static。
3. 在Levels內讀取每個子地圖,放置各自的NBV,並且罩住所需要的區域。
4. 執行Build path。navigation mesh資訊就會存入子地圖。
3. Dynamic NavMesh with World Composition

1. 在主地圖放置一個NBV,罩住全地圖範圍。
2. Editor Preferences->Level Editor->Miscellaneous->Update Navigation Automatically設為false
3. 自動產生於主地圖的RecastNavMesh-Default內,有個屬性Runtime Generation設為Dynamic。
4. Navigation mesh就會在地圖載入後開始自動計算並產生navigation mesh。
4. Lazy Dynamic NavMesh with World Composition

1. 在主地圖放置一個NBV,罩住全地圖範圍。
2. Editor Preferences->Level Editor->Miscellaneous->Update Navigation Automatically設為false
3. 自動產生於主地圖的RecastNavMesh-Default內,有個屬性Runtime Generation設為Dynamic。
4. Project Settings->Navigation System->Data Gathering Mode 設為Lazy
5. Generate Navigation Only Around Navigation Invokers 設為true
6. 在AI pawn的class 新增NavigationInvokerComponent

驗證時需注意的事項


在測試Navigation mesh的時候,最好把editor重開後,再看一次是不是正確顯示。
我有遇到Build path後有navigation mesh,PIE也正常,但是重新開啟editor後,
navigation mesh就消失不顯示的情況。
基本上是跟引擎自動產生RecastNavMesh-Default這個actor有關。

Static NavMesh


Static NavMesh是一般關卡式的作法,其實World Composition使用也是可以。
但是這個做法會把nav mesh全部存入主地圖,等於一開始讀取主地圖後,整個世界的navmesh都會被載入。

主地圖的檔案大小會很大,也會嚴重影響到初始讀取的速度。

Static NavMesh with World Composition


官方說這個方法可行,但是我測試(環境是UE 4.23)的結果是,
只有第一個sublevel(通常是X0_Y0那一張)有被讀取的時候,static navimesh才會正常運作。

舉例來說,
玩家在地圖X0_Y0往X0_Y1的地圖走,當觸發X0_Y1讀取的時候,X0_Y0以及X0_Y1兩張地圖的navigation mesh都是正常的。

但是繼續走到X0_Y0會被unload的距離時,全部的navigation mesh都會跟著被unload。

目前我還沒有找到解決的方法,不過可以知道的是就算解決了,這種靜態navigation mesh的作法仍然有一些問題,
這邊就列出使用static navigation mesh的優缺點。

優點

資料完全靜態,在遊戲中完全不需要花時間計算nav mesh。

缺點

靜態navigation mesh資料存在每張tiled level內,所以會增加讀取時間。
場景內容有更改就要重build navigation mesh,開發過程要持續維護,不然AI移動會有問題。

Dynamic NavMesh with World Composition


這個方法驗證後可以正確運作,但是在地形比較大的環境,會有嚴重的FPS下降的情況。
主因當然就是因為動態在計算大片的navigation mesh造成的。
如下圖,較大的地形被載入時需要大量的計算。


Lazy Dynamic NavMesh with World Composition


目前個人覺得可以接受的解決方案,只有在AI角色所在的區域會即時計算navigation mesh,如下圖。



實際用起來不太會感受到CPU在計算navigation mesh的延遲。
不過還是有一些缺點或是小細項是需要注意的。

因為是動態navigation mesh,所以不容易在editor模式就預覽navigation有問題的情況。
不好預覽自然就不方便修正。

角色invoker的範圍要怎麼訂,是要考慮角色大小,角色移動速度,角色移動範圍等參數的。
如果角色移動速度過快,造成navigation mesh計算來不及,就會移動失敗。
或是角色移動範圍大於產生的navigation mesh,也會形成移動失敗。

大量的角色會分散在各個地圖中,並且來回走動。
這樣的案例應該會比Dynamic NavMesh with World Composition還差。
因為來回走動造成算過的navigation mesh重複計算了(未實際驗證)。

同上,移動速度較快的角色也容易持續觸發動態navigation mesh的計算。
可能會影響CPU執行時間。

結論


上面列出了我最近有測試過開放場景的navigation mesh用法。
static navigation mesh的版本看起來如果沒有bug的話,還是很泛用,畢竟沒有任何動態的資源會被浪費。
但是以現在的實作版本,看起來選擇Lazy dynamic mesh是比較好的選擇。

參考資料


StaticNavmesh and level streaming
這兩篇的人跟我一樣想要嘗試使用static nav mesh,但是失敗了。

How to work with NavMesh and big Landscapes?
這篇最後有人提到使用Navigatiohn invoker使用的方法




留言

這個網誌中的熱門文章

UE4 除錯技巧分享 (一)

UE4 GameplayAbilitySystem - GameplayEffect & GameplayCue 如何設定參數

UE4 GameplayAbilityTask介紹