ナビメッシュリージョンの使用
Quantumナビメッシュリージョンは、(編集時)定義済みのナビメッシュのエリアです。非常に小さいパフォーマンスオーバーヘッドで、実行時にエージェント毎にオン/オフを切り替えたりフィルタリングしたりすることが可能です。リージョンは、決定論的ロールバックのパフォーマンスを考慮した、Unity動的ナビメッシュCarveの妥協案です。
利用可能なリージョン生成モードは2つあります。
| Simple | Advanced | |
| 最大リージョン数 | 29 | 512 |
| 利用手順 | UnityナビゲーションエリアIDを直接使用する | ジオメトリ内にリージョンスクリプトを追加で設定する必要がある |
モードを変更するには、QuantumMapNavMeshUnityスクリプトを選択してください。
Walkable(歩行可能)エリアは、常にリージョン0に変換され、これはMainAreaと呼ばれます。
マップすべてのリージョンはMap.Regionsリストからアクセス可能です。リージョンIDは整数で、Map.RegionMapのルックアップを使用して取得できるマップ内リージョンのインデックスを指します。
ナビメッシュリージョンのインポート - Simpleモード
シーン上のオブジェクトを選択し、NavMesh Modifierスクリプトを追加します。Override Areaを有効にし、任意のエリアタイプを設定します。UnityのNavigationウィンドウから、様々なUnityナビゲーションエリアタイプを定義できます。
QuantumMapNavMeshUnityスクリプトを選択し、Simpleリージョンのインポートモードを有効にします。そして、Quantumリージョンに変換したいUnityエリアを設定します。
Quantumナビメッシュをベイクして、ナビメッシュギズモを使用してインポートされたリージョンを確認します。リージョンはマゼンダ色で描画されます。
QuantumMapEntityを選択して、インポートされたリージョン名を確認します。
ナビメッシュリージョンのインポート - Advancedモード
UnityナビゲーションエリアID(ID数に制限がある)を直接使用せず、ベイク中にQuantumNavMeshRegionスクリプトを使用して、ナビゲーションエリアに「マーク」されたUnityナビメッシュを使用します。マークされたナビメッシュの三角形は島形状に拡張され、元QuantumNavMeshRegionのバウンディングボックスに再マッピングされることで、最終的に正しいリージョンIDが割り当てられます。
ステップ1:UnityのNavigationウィンドウ(Window > AI > Navigation)を開き、新しいナビゲーションエリア(例:QuantumRegion)を追加します。
ステップ2:MapNavMeshUnityスクリプトを選択します。Import Region ModeをAdvancedに設定して、UnityナビゲーションエリアQuantumRegionを有効にします。
ナビメッシュ三角形は100%正確には生成されないため、RegionDetectionMarginによって調整時のマージンを定義します。リージョンのインポートに失敗する場合はこの値を大きくできますが、大きすぎると隣接リージョンの検出に問題が生じる可能性があります。
ステップ3:リージョン投影スクリプトを作成します。
MeshRendererを持つゲームオブジェクトを作成/選択し、MapNavMeshRegionスクリプトをアタッチします。
UnityではMeshRendererを使用して、エリアをナビメッシュに投影します。これは、ナビメッシュサーフェスがレンダラーのメッシュを収集するように設定されていることが前提です。
MeshRendererとリージョンスクリプトは、ベイク中のみ有効化されている必要があります。
リージョンIdは、リージョンを名前でマークします。複数のMapNavMeshRegionに同じ名前を使用し、一つのリージョンにまとめることもできます。IdはマップのMap.RegionMapに登録されます。リージョンインデックスは、配列内のリージョンの位置を指します。
CastRegionをCastRegionに設定します。
ゲームオブジェクトにNavMesh Modifierを追加、Override Areaを有効にし、エリアタイプをQuantumRegionに設定します。Unity 2022以前のバージョンでは、リージョンスクリプトのNavMeshHelperを使用してエリアを切り替えられます。
リージョンが互いに密接している場合、各リージョンに異なるエリアタイプを選択してください。以下の例なら、リージョンAはQuantumRegion、リージョンBはQuantumRegion2を使用します。
ステップ4:マップとナビメッシュをベイクします。
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)
実行時のギズモでは、有効/無効のリージョンが表示されます。
|
|
マップ変更時、ISignalOnMapChangedシグナル内でFrameBase.ClearAllNavMeshRegions()を実行することで、リージョン状態をリセットできます。
C#
public class ResetRegionsSystem : SystemSignalsOnly, ISignalOnMapChanged {
public void OnMapChanged(Frame frame, AssetRefMap previousMap) {
frame.ClearAllNavMeshRegions();
}
}
NavMeshRegionMaskオブジェクトは内部のビットセットを使用して、どのリージョンを有効化するかを制御します。
| Default | すべてのリージョンが有効なリージョンマスクを作成します。 |
| MainArea | メインエリアのみを含むリージョンマスクを作成します。 |
| Empty | すべてのリージョンが無効なリージョンマスクを作成します。 |
| HasValidRegions | リージョンマスクに、少なくとも一つ以上(メインエリアを含む)有効なリージョンが設定されている場合はtrueを返します。 |
| HasValidNoneMainRegion | リージョンマスクに、有効なリージョン(メインエリアを除く)が設定されている場合はtrueを返します。 |
| IsMainArea | リージョンマスクに、メインエリアのみが含まれてるかどうかを確認します。 |
| Create(int region) | 指定したリージョンが有効なリージョンマスクを作成します。 |
| Create(int[] regionList) | リージョンIDリストを使用してリージョンマスクを作成します。 |
| ToggleRegion(int region, bool enabled) | リージョンIDを指定して、リージョンのオン/オフを切り替えます。 |
| IsRegionEnabled(int region) | リージョンが有効化どうかを確認します。 |
| Clear() | リージョンマスクをリセットして、すべてのリージョンを有効に設定します。 |