Using Navmesh Regions
Quantum 導航網格區域是預定義(編輯時)的導航網格區域,可在運行時按代理開啟 / 關閉或過濾,且性能開銷極小。考慮到確定性回滾的性能因素,區域是 Unity 動態導航網格雕刻的一種折中方案。
有兩種區域生成模式可供選擇。
簡單模式 | 高級模式 | |
最大區域數量 | 29 | 512 |
工具支持 | 直接使用 Unity 導航區域 ID | 需要在級別幾何體內設置額外的區域腳本 |
選擇QuantumMapNavMeshUnity
腳本可更改模式。
Walkable
區域始終會轉換為區域0
,並稱為MainArea
。
地圖的所有區域都可在 Map.Regions
列表中訪問。區域 ID 是一個整數,指的是該地圖內區域的索引,可通過Map.RegionMap
查找獲取。

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

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

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

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

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

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

步驟 2:選擇MapNavMeshUnity
腳本,將區域導入模式設為 Advanced
,並啟用 Unity 導航區域QuantumRegion
。
由於導航網格三角形的生成並非 100% 精確,RegionDetectionMargin
用於定義擬合期間的邊距。當區域導入失敗時,可以增大該值。但如果該值過大,可能會在檢測相鄰區域時出現問題。

步驟 3:創建區域投射器腳本。
選擇或創建一個帶有MeshRenderer
的遊戲對象,並附加MapNavMeshRegion
腳本。

Unity 使用MeshRenderer
將區域投射到導航網格上。創建一個帶有MeshRenderer
的遊戲對象,並附加MapNavMeshRegion
。前提是導航網格表面已配置為收集渲染網格。
MeshRenderer
和區域腳本只需在烘焙期間處於活動狀態。

區域Id
用一個名稱標記該區域。多個MapNavMeshRegion
可以使用相同的名稱,併為該區域貢獻內容。Id
將註冊在地圖的Map.RegionMap
下。區域索引指的是該區域在該數組中的位置。
將CastRegion
設為CastRegion
。
向該遊戲對象添加NavMesh Modifier
腳本,啟用Override Area
,並將 QuantumRegion
設為區域類型。在 Unity 2022
及更早版本中,區域腳本上的NavMeshHelper
可用於切換區域。

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

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

區域 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 顯示啟用和禁用的區域。
![]() |
![]() |
更改地圖時,可以在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() | 重置掩碼並將所有區域設為啟用狀態 |