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() | 重置掩碼並將所有區域設為啟用狀態 |