UDN
Search public documentation:

NavMeshConstraintsAndGoalEvaluatorsJP
English Translation
中国翻译
한국어

Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

ナビゲーション メッシュ パス制約と終点評価

ドキュメント概要: パス制約、パス終点評価、使用方法、書き方の概要と説明。

ドキュメントの変更ログ: Matt Tonks により作成。

概観

このドキュメントは、パス検索と一般的なパス トラバーサルに関するパス制約とパス終点評価の目的と使用法を解説します。

なぜでしょうか? これらのモジュールとカスタム可能な制約の到来は、AI プログラマが、ほとんどコードのオーバーヘッドなしに、ゲームのニーズにちょうど合うように調整されたパス クエリーを実行することを可能にします。過去には、 敵を避けるような A->B のパスを見つけたい場合 、パスへのブロックが Native コードに関数が必要な場合、特例を追加して、新しい状況ごとにそうし続けなければいけませんでした。これは、すぐに不便になります。各異なるコンビのカスタム判断 (制約) で、特定のパス検索が必要であり、それぞれの新しいクエリーを考慮するために、新しいコードが追加されなければいけません。私たちのアプローチは、パス検索中にすべてが考慮されるようなリストに追加されるような pathconstraints と呼ばれる内蔵型のオブジェクトにまとめることです。従って、もし目的地へのもっとも短いパスを見つけようとしているならば、単純に navmeshpath_toward 制約を追加します。これは、AI プログラマがお気に入りとしている従来の直線 A* ヒューリスティックを提供します。しかしながら、例えば射撃を避けるような a->b のもっとも短いパスを見つけるような、より複雑なことがしたい場合は、 toward 制約と avoidfire 制約の両方を追加します。これは簡単に行うことができ、スクリプト アクセス可能なので、カスタムをまとめるのが容易になり、1 回のパス クエリーで状況に合わせることができます。

しかし、制約は全体像の半分に過ぎません。パス検索の完了条件を指定する機能と、データが行き来すると同時にそれをチェックする可能性が必要となります。これのために、終点評価があります。これらは両方とも検索が終了時 (例: 有効な終点ノードを見つけた場合)、またチェックの処理と計算されたデータの格納時に命令を出します。例えば Gears では、カバーを探している場合、 cover goal evaluator が使用されます。このカスタム終点評価は、十分なクオリティの covernode が見つかるまで検索を続け、そこまでで見つかった covernodes をトラックし、途中で記録していきます。より基本的な (そして一般に使用される) 終点評価は navmeshgoal_at であり、これは、検索終点ポイントを含む navmesh ポリゴンが見つかると単に検索を中止します。これは、A->B のもっとも短いパスを見つけるのに使用する終点評価です。

制約と終点評価は、 ナビゲーション ハンドル の 2 つのリストに格納されています。各パス ステップ中、 UNavigationHandle::ApplyConstraints が呼び出されます。これは、リスト内の各パス制約にヒューリスティックを変更する可能性と任意のポリゴンの実際のコストを提供します。同様に、新しいノード (ポリゴン) が開かれたリストから取り出されると、 UNavigationHandle::EvaluateGoal が検索終了を呼び出す可能性を各パス終点評価に提供し、ポリゴンをチェックします。

パス制約

(NavMeshPathConstraint.uc)

上記したように、パス制約は、格納された実際の距離 (g) とヒューリスティック距離 (h) の両方を変更することができます。最後に、パス制約は、このノードが不適切であり、開かれたリストに追加されるべきではないということを示すような特定のノードで FALSE を返すこともできます。

パス制約が使用されるべき状況は以下の通りです。

  • 終点に向かってトラバーサルを形作る場合 (例: 最初に終点に向かうノードを試すことによって検索を最適化する)
  • 条件的にトラバース不可能なエリアでトラバーサルを制限する場合 (例: 炎、溶岩、見方専用のドア)
  • 望ましくないオブジェクト (例: 敵プレイヤー) からトラバーサルをずらす場合

パス制約を使用できない状況は以下の通りです。

  • データの収集/格納 (前回の制約が FALSE を返すと、制約が呼び出されない可能性がある)
  • コーヒーを入れる

たいていのパス制約は、ベースのインターフェース関数を実装することのみが必要です。

   /**
    * EvaluatePath – A* 継承エッジごとに、この関数が呼び出されます。これは、制約に可能性を提供します。
    * ヒューリスティック コスト (h) と計算された実際のコスト (g) の両方を変更、そしてこのエッジの使用を完全に拒否するには…
    * @param Edge – 継承候補となるエッジです。
    * @param SrcPoly – ここからポリゴンを拡張します (例: Edge をトラバースしたいものからのポリゴン)。
    * @param DestPoly – (SrcPoly から) トラバースしようとしているあて先のポリゴンです。
    * @param PathParams – パス コントロールするエンティティのキャッシュされたパス コントロール パラメータです。
    * @param out_PathCost – このエッジの計算されたパス コストです (現在の値は入力として提供され、この関数内で変更することができます)。
    *                       (これは、パス検索ヒューリスティック関数 F=G+H の G です。)
    * @param out_HeuristicCost – このエッジに適用されるヒューリスティック コストです (現在のヒューリスティックは入力として提供され、この関数内で変更することができます)。
    *                          (これは、パス検索ヒューリスティック関数 F=G+H の H です。)
    * @return – このエッジが有効な継承候補である場合は TRUE で、開かれたリストに追加され、処分されるべきである場合は FALSE になります。
    */
   virtual UBOOL EvaluatePath( FNavMeshEdgeBase* Edge,
                        FNavMeshPolyBase* SrcPoly,
                        FNavMeshPolyBase* DestPoly,
                        const FNavMeshPathParams& PathParams,
                        INT& out_PathCost, INT& out_HeuristicCost );

パス終点評価

(NavMeshPathGoalEvaluator.uc)

パス終点評価は、開始と終了のノードを決定したり、検索が何らかの理由で中止された場合、どのノードを「終点」と呼ぶかを決定したりなどの基本的なパス検索機能を処理するので、少し複雑だと言えます。終点評価は検索をセットアップし、いつ完了するかを決定し、また見つかるとナビゲーション ハンドルにパスを保存します。 備考: リスト内の 最初の pathgoalevaluator には、特別な意味があります。これは、マスター評価として扱われるので、検索の初期化のコントロールを握っています (例: seedworkingset、initializesearch)。

以下が典型的なパス終点評価のサイクルです (これは、すべて UNavigationHandle::GeneratePath() 内で起こります):

  • InitializeSearch() が、パス検索の一番最初に呼び出されます。これによって、終点評価が検索を進めるのに必要なすべてをセットアップできるようになります。デフォルトの機能は SearchStart を含むポリゴンを見つけ、AnchorPoly として設定します。

  • 次に SeedWorkingSet() が呼び出されます。この関数は、1 つ以上のポリゴンを開かれたリストに投入する役目をし、ここから検索を開始します。デフォルトの機能は、アンカー ポリゴンを作業セットに追加するだけです。

ここで、パス検索のメイン ループに入ります。

  • 作業セットから最善のノードが取り出されると、 EvaluateGoal() が呼び出されます。この関数は、パス終点評価リストをチェックして、EvaluateGoal() を順番に呼び出していきます。これは、リスト内の各終点評価がポリゴンをチェックすることを可能にし、適切なノードが見つかったら検索を中止することもできます。

  • パスが完了すると、 DetermineFinalGoal() が呼び出されます (終点が見つかったか、検索でテストするノードがなくなったためです)。これは、終点評価の最終計算を可能にし、(もしある場合は) 実際の最善の終点はどれかを決定します。ここでのデフォルトは、終点が見つかったかどうかをチェックするだけですが、navmeshgoal_atcover のようなより複雑な評価では、今まで訪れたポリゴンの最終ストックを取得し、もっとも適切な終点はどれかを決定します。

  • SaveResulingPath() は、評価で一番最後に呼び出される関数です。ほとんどすべての終点評価で、この関数は、開始から終点までのパスを保存するために、先行チェーンを反対に歩きます。しかし、これはカスタム評価がここで少し違ったことを行うようにします。例えば、(終点から開始へのパス検索をする) navmeshgoal_closestactorinlist は、逆に開始へ向かうので、パスを前向きに保存します (この評価に関する詳細は以下を参照)。

  • NotifyExceededMaxPathVisits() も、例外で呼ばれる関数です。ナビゲーション ハンドルで、訪れたポリゴンの数が MaxPathVisits パラメータを超す場合、これが呼び出されます。たいていの場合、これは失敗を示します (例: 最大サンプル サイズ内で終点が見つからなかった)。しかし、時によって、これは検索が完了したことを示すだけのこともあります (例: navmeshgoal_null はノードがなくなるまで、または訪れることのできる最大数に到達するまで検索します。これは、エリアで最善のノードを見つけるのに有用です)。

新しい pathgoalevaluators によって実装される必要のある唯一の関数は EvaluateGoal です。これは、終点評価の主な関数です (有効な終点が見つかった際に決定するということです)。

EvaluateGoal の動作の仕方に影響を与えるブーリアンがいくつかあります。99% のトラバーサルで、デフォルト設定を使用しますが (そして、実際にほとんどのトラバーサルは 1 つしか終点評価がないので、これらは問題にもなりません)、終点評価の構成にとって、これらのブーリアンを追加することは、物事をより簡単にします。

  • (UNavigationHandle 上の) bUseORforEvaluateGoal - デフォルトで すべての 終点評価は、EvaluateGoal() から TRUE を返さなければいけません。これは、検索が終了したとみなされるようにするためです。これは、ナビゲーション ハンドルの bUseORforEvaluateGoal で変更することができます (TRUE の場合、どれかの終点評価が EvaluateGoal から TRUE を返すと、検索は中止されます)。
  • (GoalEvaluator 上の) bAlwaysCallEvaluateGoal - これが、TRUE の場合、現在のノードが最終終点である、またはそうでないと既に決定されていても、特定の終点評価に goaleval の EvaluateGoal 関数が呼び出されます。これは、情報を格納しなければいけない終点評価や、各パス イテレーションで何かを計算しなければいけないような終点評価にとって便利です。

Constraint/GoalEval プール化

不必要なパス制約や終点評価を常に新しくすることを避けるために、これらはオンデマンドやキャッシュで新しくされます。これは、キャッシュされた制約や終点評価を、新しくしたり、数々の制約をガーベジ コレクションせずに、再利用することを可能にします。

この目的のために、pathconstraints や goalevaluators を直接新しくするべきではありません。その代わりに、navigationhandle で CreatePathConstraintCreatePathGoalEvaluator を呼び出します。これは、まだキャッシュされていない場合、その制約のコピーを新しくするか、キャッシュされたコピーを取得します。

キャッシュ プロセスの一部として、ハンドルから制約がクリアされた場合、 Recycle() イベントが呼び出されます。この関数内で、すべての状態がクリアされ、デフォルトにリセットされます。pathconstraints と goalevaluators をオーバーライドする際に、リサイクルされた制約に古いデータがくっついてこないように、この関数をオーバーライドして、派生クラスの一部となり得る新しい状態をクリアすることが重要です。

使用例

制約や評価をハンドルのリストに追加するために呼び出せるように、制約/評価で静的関数を実装することは便利です。以下が navmeshpath_toward 制約のそのような静的関数の例になります。
static function bool TowardGoal( NavigationHandle NavHandle, Actor Goal )
{
   local NavMeshPath_Toward Con;

   if( NavHandle != None && Goal != None )
   {
      Con = NavMeshPath_Toward(NavHandle.CreatePathConstraint(default.class));
      if( Con != None )
      {
         Con.GoalActor = Goal;
         NavHandle.AddPathConstraint( Con );
         return TRUE;
      }
   }

   return FALSE;
}

ご覧のように、これは CreatePathConstraint を呼び出し、そのクラスのキャッシュされたバージョンを取得し、その後 AddPathConstraint を呼び出し、検索中に使用される制約のリストに配置します。

AddPathConstraintAddGoalEvaluatorClearConstraints は、トラバーサルの制約を指定するためのインターフェースです。

備考: 通常、 ClearConstraints() を呼び出すことは必要ありません。これは、FindPath() を呼び出した後、自動的に制約がクリアされるからです。

FindPath() に関する詳細な情報とその使用法に関しては、ナビゲーション メッシュ テクニカル ガイド?を参照してください。また、パス検索のデバッグ方法に関する情報は、NavigationMeshPathDebuggingJP ページを参照してください。

現在のパス制約の概要と使用法

NavMeshPath_Toward

これは、パスされた終点ポイントへの距離に従って、ヒューリスティック コストを追加します。特定の終点に向かう法線パス検索をバイアスする場合に、これを使用します。

NavMeshPath_AlongLine

これは、指定された方向からより遠いノードへ、ヒューリスティック コストを追加します。

NavMeshPath_EnforceTwoWayEdges

対応するエッジ バックをもたないエッジをフィルタ アウトします (出られないような状況に AI が陥ることを防ぎます)。

NavMeshPath_MinDistBetweenSpecsOfType

特定のタイプのエッジ間に最小の距離があることを確保するために、各ステップで先行チェーンに沿って歩いて戻ります (例えば、マントル間で最小距離を確保する)。

NavMeshPath_WithinDistanceEnvelope

ユーザーがエンベロープを指定できるようにします。このエンベロープ内では、パスが有効であり、ノードをこのエンベロープ外に出すか、エンベロープから出ると同時に次第にペナルティーを科すかどうかを指定することができます (例: 自分にとって最大範囲内のポイントを見つけたい場合)。

NavMeshPath_WithinTraversalDist

指定された値を超えるパスを処分します。

現在のパス終点評価の概要と使用法

NavMeshPath_At

もっとも単純で一般的な終点評価です。終点ポイントを含むポリゴンが見つかったら、検索を終了します。

NavMeshPath_ClosestActorInList

より興味深い終点評価の 1 つです。これは、効率的に要求中のエンティティに (パス距離内の) もっとも近いアクタを見つけます。これは、検索を反対に行うことで達成されます。検索するリスト内のアクタを含むようなすべてのポリゴンが、作業セットに提供され、searchstart を含むポリゴンが見つかるまで検索は続けられます。既に反対に行っているので、この時点で、パスは前向きの順序で保存されます。

NavMeshPath_Null

この終点評価は、単にイテレーションの最大数に到達するまで、または検索するノードがなくなるまで、検索を続けます。エリア内の最善のノードを見つけるのに便利です (例: navmeshpath_distanceenvelope 制約とともに用いて、最大範囲内でもっとも遠いポリゴンを見つけるのに使用する)。