A *ナビゲーションメッシュパス検出


15

だから私は、Greenfootと呼ばれるこのフレームワークでこのトップダウン2D Javaゲームを作り、あなたが戦うつもりの人のためにAIに取り組んでいます。彼らが世界を現実的に動き回ることができるようにしたいので、すぐに、他のいくつかのことの中で、何らかの経路探索が必要になることに気付きました。

2つのA *プロトタイプを作成しました。1つはグリッドベースで、ウェイポイントで動作するものを作成したので、障害物/建物の2D「マップ」からパスを作成できるノードのグラフに到達する方法を考え出す必要があります。実際の経路探索はうまくいくように見えます。私の開いたリストと閉じたリストだけがより効率的なデータ構造を使用できますが、必要に応じて必要なときにそれを取得します。

ai-blog.netのこの投稿に記載されているすべての理由で、ナビゲーションメッシュを使用する予定です。しかし、私が直面した問題は、ノードの任意の部分を移動する場合、A *がポリゴンの中心/エッジからの最短経路であると考えるものが必ずしも最短経路ではないことです。より良いアイデアを得るために、私はstackoverflowで私が尋ね質問を見ることができます。

可視性グラフに関する良い答えを得ました。それ以来、私はこの本(Computational Geometry:Algorithms and Applications)を購入し、このトピックをさらに読みましたが、ナビゲーションメッシュの方が好きです(AmitのPath-Findingに関する注意の複雑さの管理」を参照)。(補足として、最初と最後が隠されていない場合、Theta *を使用して複数のウェイポイントを1つの直線に変換できます。または、最後の前のウェイポイントにチェックを戻すたびに、直進できるかどうかを確認しますこれに)

基本的に私が欲しいのは、一度ファンネルアルゴリズムを通過させたナビゲーションメッシュです(たとえば、Digesting Duckのこのメッシュ)、ノードからノードのみに続く最短パスであるものではなく、真の最短パスを取得します。ただし、一部のポリゴンを通過してノード/エッジをスキップできる場合、実際の最短ではありません。

また、ポリゴンに関する情報を保存することをどのように提案するかも知りたいです。作成したウェイポイントプロトタイプの例では、各ノードをオブジェクトとして使用し、そのノードから移動できる他のすべてのノードのリストを保存しました。ポリゴンでは機能しないと思いますか?そして、ポリゴンがオープン/トラバース可能かどうか、またはソリッドオブジェクトかどうかを確認するにはどうすればよいですか?ポリゴンを構成するノードを保存するにはどうすればよいですか?

最後に、記録のために:既に他のソリューションが利用可能であり、このゲーム以外でこのコードを使用するつもりはないので、私はこれをゼロから自分でプログラムしたいと思います。必然的に品質が低下します。


よく わかりませんが、これらのリンクが役立つ場合があります:gamedev.stackexchange.com/questions/1327/…gamedev.stackexchange.com/questions/8087 / ...また、今は見つけられないパス検索についての別の質問がありました、賞金を得て、非常に良い答えがありました。
Ali1S232

はい、2番目のリンクでは、A *アルゴリズムは、エッジの中間点を使用して最短経路としてA *アルゴリズムによって最下部のパスを与えますが、実際には障害物の最上部の周りのパスは最短です。A *を取得して上部のパスを取得する方法を知りたいのですが、真っ直ぐに(たとえば漏斗アルゴリズムによって)真っ直ぐにして真下の最短パスを取得します。まっすぐにしても、まだ迂回しています。
angrydust

実際には、gamedev.stackexchange.com / questions / 8087 / の記事を読んだだけで、A *でルートを見つけ、修正されたファネルアルゴリズムで真のコストを計算し、別のルートを見つけて計算することで機能しているようです。再び真のコストを求め、それが他のものよりも短いかどうかを確認します。最短ルートが見つかったことがわかるまで繰り返されます。これは確かに私の問題を解決しますが、直線化と経路探索の両方を繰り返しているため、非常に時間がかかるようです。これは非常にコストがかかります。
angrydust

ポリゴンストレージ:表示されているポリゴンのみを保存するか、タグを各ポリゴンに関連付けます(各ポリゴンは頂点の円形リストである必要があることを忘れないでください)。同様に、ノードを使用して、元のポリゴンのIDを保存できますが、これを伝える必要はありません。これは基本的なデータストレージです。最後に、本当の最短経路をにするのはなぜですか?あなたのゲームは犬を遅く走らせるか、わずかに不正確なパスを持つことができます。真の最短経路を得ることREQUIRES(少なくともノードグラフ上)完全幅優先探索を。
ジョナサンディキンソン

@JonathanDickinson最後のピクセルまで100%正確なパスは必要ないことを知っています。A*を使用して、最大pのパスを生成できることを知っています。スタックオーバーフローに関する以前の質問またはgamedev.stackexchange.com/questions/8087 / ...にあるように、問題は障害物をはるかに超えて進んでいます。AIを障害物の周りをそのように歩かせることはできません!
angrydust

回答:


14

独自のコードをすべて作成する場合でも、生成されたnavmeshを表示する視覚化機能を備えたRecastをダウンロードし、サンプルアプリケーションをビルドすることをお勧めします。インターフェース。それで遊ぶだけで多くを学ぶことができます。

すでに理解しているように、見栄えの良いパスを作成するには2つのステップがあります。A*パスファインダーと、その後のパスの矯正(障害物を避けるために不要なターンの除去)を含む後処理です。転換点での曲線の追加。

経路探索

A *パートをマスターしました。これは素晴らしいことです。また、A *が常に最もまっすぐな経路を見つけるとは限らないという観察も行っています。これは、A *がグラフに最短経路を見つけるアルゴリズム(ノードが無次元である数学的な概念である)をメッシュに適用するときに、何らかの方法でノードをメッシュ要素にマップする必要があるためであることを理解することが重要です。

最も明白なことは、ポリゴンの中心点から中心点に移動し、この距離に基づいてコストを計算することですが、これにはいくつかの問題があります。1つは常に幾何学的に最短のパスを見つけられないことであり、2つ目はそこで計算したパスをたどると、ある中心から次の中心への直線がパスの一部ではありません(また、まったくナビゲートできない場合もあります)。A *の実行中にグラフの走査にコストをかけるのはひどい方法ではありませんが、走査の目的には明らかに十分ではありません。

次に簡単な解決策は、メッシュを介してエッジからエッジへA *を実行することです。ポリゴンごとに1つのノードではなく、エッジごとに1つ、ポリゴンごとに1つのノードがあると想像すれば、このことを考えるのがより簡単になります。したがって、パスは開始点から最も近いエッジのすぐ内側に進み、隣接するポリゴンのエッジのすぐ内側を通過してから、同じポリゴンの次のエッジのすぐ内側に移動します。これにより、最短経路がより頻繁に生成され、経路の直線化手順を実行したくない場合に通過できるという利点もあります。

経路矯正

Detour(Recastに付属するナビゲーションライブラリ)で使用されるアルゴリズムは非常に単純です。A *検索中に見つかったポリゴンの境界内でのみパスが直線化されることに注意してください。そのため、それが障害物の周りで最もタイトなパスを見つけられない場合、そのアルゴリズムを実行した後もタイトなパスを取得できません。実際には、リキャストによって生成されるnavmeshesは、チョークポイント(2つの障害物間の最も近いポイント)をナビゲートするときに通過できる単一のポリゴンを持つ傾向があるため、A *は常に障害物に近いノードのリストを生成します可能。タイルをnavmeshとして使用している場合、これは当てはまりません。この非常に単純なアルゴリズムは、誤ったターンを挿入します。

Detourのパスストレートニングアルゴリズムは、ターンを挿入する必要があると判断すると、最後にファンネルを左に締めた位置に挿入するため(左に回したとき、およびその逆の場合)、その後、そのポイントから再びノードのトレースを開始します。

A *ルートの一部を形成するポリゴンの外側のパスをまっすぐにしたい場合、事態はさらに複雑になります。navmeshの2つのポイントが互いに見えるかどうかをテストできるレイキャストルーチンを実装する必要があります(とにかくこれを使用して、A *を使用する必要があるかどうかを確認してください)。これを行うには、origin-> targetによって形成されたラインセグメントを、原点を含むポリゴンの接続エッジと交差させ、次に移動するポリゴンの接続エッジをテストします。接続していないエッジと交差する場合(境界エッジと呼びます)、障害物にぶつかります。

その後、ファネリングアルゴリズムがターンを挿入する必要があると判断したときにこのレイキャストテストを実行して、実際に実行するかどうかを確認できますが、ターンを挿入するまですべてのノードでそのテストを実行し続ける必要があると思います(その時点で、簡単なファンネルアルゴリズムに戻すことができます)。それは高価になり、経路をほぼO(n ^ 2)に直線化します。

navmeshの表現

メッシュをポリゴンクラスの配列として表すことができます。ポリゴンクラスは、頂点の配列や、各エッジに隣接するポリゴンがある場合は隣接するポリゴンへの参照の配列と同じくらい簡単です。もちろん、もっとコンパクトに保存する方法を考えることができます。通常、頂点は複数のポリゴンで共有されるため、1つの大きな頂点の配列を作成し、各ポリゴンにその配列にインデックスを格納させるのが普通です。navmeshの特性によっては、接続エッジの平均数はエッジの数の50%以下である場合があります。その場合、すべてのエッジのリンクを保存するのではなく、別のポリゴンへのリンクとエッジのインデックスを保存することができます。また、クラス参照を使用するのではなく、navmeshのポリゴン配列にポリゴンのインデックスを保存することをお勧めします。


私はちょうどA *のために簡単には、この読みましたが、私はあなたが距離の二乗(またはしない平方根それを)使うべきではありません理解してきました:theory.stanford.edu/~amitp/GameProgramming/...
angrydust

私は実際にパスをまっすぐにする方法についてはあまり心配していません。私が心配しているのはあなたが言うことです:「A *検索中に見つかったポリゴンの境界内でのみパスをまっすぐにすることに注意してくださいそのため、それが障害物の周りで最もタイトなパスを見つけられない場合、そのアルゴリズムを実行した後にもタイトなパスを取得できません。」
angrydust

頂点/中間点を経由して移動するコストに関係なく、A *が一度直線化された経路が常に最短になるナビゲーションメッシュが必要です。これは可視性グラフで行うことができますが、他の多くの利点があり、可視性グラフの複雑さが急速に大きくなる可能性があるため、navmeshを使用したいと思います:theory.stanford.edu/~amitp/GameProgramming/…
angrydust

@theguywholikeslinuxでは、ユークリッド距離を使用できますが、sqrt(x*x + y*y)ノードあたりの安価な距離は使用できませんx*x + y*y
ジョナサンディキンソン

@JonathanDickinson私は知っているので、私のポイント。
angrydust
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.