This document is about: QUANTUM 3
SWITCH TO

Using Navmesh Regions

Quantum 導航網格區域是預定義(編輯時)的導航網格區域,可在運行時按代理開啟 / 關閉或過濾,且性能開銷極小。考慮到確定性回滾的性能因素,區域是 Unity 動態導航網格雕刻的一種折中方案。

有兩種區域生成模式可供選擇。

簡單模式 高級模式
最大區域數量 29 512
工具支持 直接使用 Unity 導航區域 ID 需要在級別幾何體內設置額外的區域腳本

選擇QuantumMapNavMeshUnity腳本可更改模式。

Walkable區域始終會轉換為區域0,並稱為MainArea

地圖的所有區域都可在 Map.Regions列表中訪問。區域 ID 是一個整數,指的是該地圖內區域的索引,可通過Map.RegionMap查找獲取。

Region Import Modes
Region Import Modes

導入導航網格區域 - 簡單模式

選擇一個場景對象,為其添加NavMesh Modifier腳本,啟用Override Area並設置所需的區域類型。在 Unity 導航窗口中定義更多 Unity 導航區域類型。

NavMesh Modifier
NavMesh Modifier

選擇QuantumMapNavMeshUnity腳本,啟用Simple區域導入模式。然後切換應轉換為 Quantum 區域的 Unity 區域。

NavMesh Modifier
NavMesh Modifier

烘焙 Quantum 導航網格,並使用導航網格 gizmos 驗證導入的區域。區域以洋紅色顯示。

Baked simple region
Baked simple region

選擇QuantumMapEntity可查看導入的區域名稱。

NavMesh map
NavMesh map

導入導航網格區域 - 高級模式

由於 Unity 導航區域 ID 的數量有限,因此不直接使用它們,而是在烘焙期間使用QuantumNavMeshRegion腳本將 Unity 導航網格的部分區域「標記」為導航區域。標記的導航網格三角形會擴展為島嶼,然後匹配回它們原始的 QuantumNavMeshRegion邊界框,最終獲得正確的區域 ID。

Unity navmesh
Unity navmesh

步驟 1:打開 Unity 導航窗口(Window > AI > Navigation),添加一個新的導航區域,例如命名為QuantumRegion

Unity Navigation window
Unity Navigation window

步驟 2:選擇MapNavMeshUnity腳本,將區域導入模式設為 Advanced ,並啟用 Unity 導航區域QuantumRegion

由於導航網格三角形的生成並非 100% 精確,RegionDetectionMargin 用於定義擬合期間的邊距。當區域導入失敗時,可以增大該值。但如果該值過大,可能會在檢測相鄰區域時出現問題。

Add Region Area
Add Region Area

步驟 3:創建區域投射器腳本。

選擇或創建一個帶有MeshRenderer的遊戲對象,並附加MapNavMeshRegion腳本。

Region Setup
Region Setup

Unity 使用MeshRenderer將區域投射到導航網格上。創建一個帶有MeshRenderer的遊戲對象,並附加MapNavMeshRegion。前提是導航網格表面已配置為收集渲染網格。

MeshRenderer和區域腳本只需在烘焙期間處於活動狀態。

Region Setup
Region Setup

區域Id用一個名稱標記該區域。多個MapNavMeshRegion可以使用相同的名稱,併為該區域貢獻內容。Id將註冊在地圖的Map.RegionMap下。區域索引指的是該區域在該數組中的位置。

CastRegion設為CastRegion

向該遊戲對象添加NavMesh Modifier腳本,啟用Override Area,並將 QuantumRegion設為區域類型。在 Unity 2022及更早版本中,區域腳本上的NavMeshHelper可用於切換區域。

Region Setup
Region Setup

當區域彼此靠近時,為每個區域選擇不同的區域類型。例如,區域A使用QuantumRegion,區域B使用QuantumRegion2

Region Setup
Region Setup

步驟 4:烘焙地圖和導航網格

Baked simple region
Baked simple region

區域 API

獲取Foo區域並全局禁用它。

C#

var regionId = frame.Map.RegionMap["Foo"];
frame.NavMeshRegionMask->ToggleRegion(regionId, false);

NavMeshPathfinder組件也有一個RegionMask,可用於為各個代理關閉區域。

C#

var regionId = frame.Map.RegionMap["Foo"];
var agent = f.Unsafe.GetPointer<NavMeshPathfinder>(entity);
agent->RegionMask.ToggleRegion(regionId, false)

運行時 gizmos 顯示啟用和禁用的區域。

Inactive Regions Inactive Regions

更改地圖時,可以在ISignalOnMapChanged信號期間運行FrameBase.ClearAllNavMeshRegions()來重置區域狀態。

C#

public class ResetRegionsSystem : SystemSignalsOnly, ISignalOnMapChanged {
    public void OnMapChanged(Frame frame, AssetRefMap previousMap) {
        frame.ClearAllNavMeshRegions();
    }
}

NavMeshRegionMask對象使用內部位集控制哪些區域處於啟用狀態。

默認 創建一個所有區域都啟用的區域掩碼
MainArea 創建一個只包含主區域的區域掩碼
Empty 創建一個沒有啟用區域的區域掩碼
HasValidRegions 如果掩碼至少設置了一個有效的區域(包括主區域),則返回true
HasValidNoneMainRegion 如果掩碼包含主區域以外的區域,則返回true
IsMainArea 檢查掩碼是否只包含主區域
Create(int region) 創建一個啟用了一個區域的NavMeshRegionMask
Create(int[] regionList) 使用區域 ID 列表創建一個掩碼
ToggleRegion(int region, bool enabled) 使用區域 ID 開啟或關閉一個區域
IsRegionEnabled(int region) 測試一個區域是否啟用
Clear() 重置掩碼並將所有區域設為啟用狀態
Back to top