Navmeshリージョンを使用する
Quantumにおける決定性ロールバックのパフォーマンス要件を尊重する一方、navmeshリージョンはUnitys dynamic navmesh carvingの妥協案となっています。これらを使用して、事前に定義しておいたnavmeshのエリアを動的に、最小限のパフォーマンスオーバーヘッドでトグルすることができます。
リージョンはマスクとしてトライアングルの内側にエンコードされているため(unsigned long)、マップごとのさまざまなリージョンIDの最大数は64となります(Navigation.Constants.MaxRegions
)。別のリージョンに同じIDを再度使用することも可能です。
主なQuantum navmesh (Walkable)は、リージョンではなく、トグルすることはできません。
Navmesh Regionsを作成する
ステップ 1) Quantum Regions piggy-back on the Unity navmesh areas. 新しいエリアを作成します。以下の画像ではToggleable
という名前を選択していますが、どのような名前でも構いません。
隣同士にトグル可能なリージョンがある場合検出されるようにするには、異なるエリアIDを使用する必要があります。その場合、こちらで複数のエリアを作成します。
ステップ 2) MapNavMeshUnity
に新しいエリアを追加します。これを行わないと、ベイキングがどのエリアを検出すべきが把握できません。
ステップ 3) UnityはMeshRenderer
オブジェクトを使用してnavmeshにエリアを投影します。MeshRenderer
を使用してGameObjectを作成し、MapNavMeshRegion
をアタッチします。
Id
は、コードからMap.RegionMap
を通してアクセス可能な一意の文字列です。Map.RegionMap
からは後でリージョンIDを取得するとこができます(int, flag)。
CastRegion
は CastRegion
に設定する必要があります。スクリプトは例として、navmeshにリージョンを投影する必要のないOff Mesh Linksに再利用されます。
NavMeshHelper
では、正しくGameObjectが設定されているかダブルチェックを行うことができます。例えば、static
に設定されているか、選択されているエリアが自分たちのリージョンエリアであるかどうかなどです。
navmeshサーフェスがインストールされている場合、インスペクターの表示は若干異なります。例えばnavmeshエリアを設定するには、NavMeshModifier
スクリプトを追加する必要があります。
リージョンインポートの間、トライアングルの元のリージョンスクリプトへのマッチを試み、そのためにメッシュの境界ボックスを使用します。
生成されたトライアングルは100%正確ではないため、MapNavMeshUnity
の設定には、フィッティング中にルームを少し追加するRegionDetectionMargin
設定があります。
リージョンがエキスポートされていない場合はこの値を増やします。ただし、この値が大きくなりすぎている場合は隣り合うリージョンに問題がある可能性があります。
リージョンを生成するMeshRenderer
はベイキングの間のみアクティブにしておく必要があります。こちらについてツールを追加したいと思います。
ステップ 4) マップをベイクしてトライアングルの色のついたエリアをリージョンが配置されたnavmeshで表示します。
ステップ 5) コード内でリージョンをオフに切り替え、エージェントがこれを回避するのを確認します。
C#
public override void OnInit(Frame f) {
var regionId = f.Map.RegionMap["foo"];
f.NavMeshRegionMask->ToggleRegion(regionId, false);
}
ステップ 6) リージョンアクティベーションがアクセス可能になり、フレーム内に保管されます。
新しいマップをロードする場合、マスクをリセットする必要があります。ISignalOnMapChanged
シグナルの間などは、FrameBase.ClearAllNavMeshRegions()
を実行します。
C#
public class ResetRegionsSystem : SystemSignalsOnly, ISignalOnMapChanged {
public void OnMapChanged(Frame f, AssetRefMap previousMap) {
f.ClearAllNavMeshRegions();
}
}
NavMeshRegionMask
オブジェクトのAPIを確認します。以下は概略です。:
NavMeshRegionMask.Default
は、すべてのリージョンを有効にします。(1に設定)NavMeshRegionMask.ToggleRegion(int region, bool enabled)
は、リージョンIDでリージョンを切り替えます。リージョンIDはビットシフトのオフセットで、Map.RegionMap
ディクショナリを使用、名前で取得できます。NavMeshRegionMask.IsRegionEnabled(int region)
は、リージョンがアクティブであるかどうかチェックします。NavMeshRegionMask.IsSubset(NavMeshRegionMask)
は、1つのマスクでアクティブになっているリージョンがすべて、他のマスクでも有効化されているか確認するのに使用します。NavMeshRegionMask.Clear()
は、すべてのリージョンをアクティブに設定します。NavMeshRegionMask.HasValidRegions
は、マスクに1つ有効オなリージョン設定をされている場合にtrueを返します。NavMeshRegionMask.IsMainArea
は、メインのnavmeshエリアに属するトライアングルに対してtrueであり、オフに切り替えられないマスクがゼロか確認します。