同人サークルA-Nestの技術メモです。

翻訳元ページ

A* Pathfinding Projectを始めよう

A* パスファインディングプロジェクトを始めましょう。

このチュートリアルでは、新しいシーンにプロジェクトをセットアップし、障害物を避けながら動くシンプルなAIを作成する方法を学びます。

あなたが書くこのAIは、あまり高度なものではなく、移動して経路をたどるために必要な最小限のコードです。より高度なAIを作りたい場合は、このチュートリアルで書くスクリプトを拡張するか、パッケージに含まれるAIPathやRichAIスクリプトを使用(または拡張)します(RichAIコンポーネントの基本的な使用方法はパート2を参照してください)。

ダウンロード方法

まだの方は、まず、A* Pathfinding Projectをダウンロードしてください。

プロジェクトはここからダウンロードできます。このプロジェクトは、いくつかの機能が制限された無料版(それでも非常に強力です)と、よりクールな機能が含まれるプロ版のどちらかをダウンロードすることができます。もし望むなら、次のセクションを始める前に、プロジェクト内のさまざまなサンプルシーンを探索することができます。

モバイル/UWP向けのデプロイメント

どのプラットフォーム向けに構築するかによって、このページを最初に読むと良いでしょう。
モバイル/UWP向けのデプロイメント

トラブルシューティング

この段階で、もしコードからコンパイラエラーが出るようなら、まずアップグレードガイドを確認してください。

それでもエラーが出る場合は、フォーラムを見て、同じ問題を抱えている人がいないかどうか確認するか、そこに新しい質問を投稿してください。

概要

パッケージには、いくつかの異なる部分があります。大まかには、以下のように分類されます。
  • 移動スクリプト: エージェントに移動方法と移動先を指示します(移動スクリプトを参照)。
  • グラフ(Graph): エージェントが移動できる場所を記述します(グラフの種類を参照)。
  • 一時的な障害物:ナビメッシュに穴をあけたり、他の方法で更新します(「ランタイム中のグラフ更新」を参照)。
  • オフメッシュリンク:エージェントがナビメッシュの他の部分間を移動またはジャンプできるようにします(ノードリンク2参照)。
  • パスモディファイアは、パスを滑らかにするなどの後処理を行います(モディファイアの使用参照)。

主に操作するのは、移動スクリプトとSeekerコンポーネントです。両方とも、移動する必要のあるエージェントにアタッチする必要があります。移動スクリプトは、エージェントの移動方法、速度、回転などを制御し、またエージェントの現在の目的地は何か、いつ経路を再計算するかなどを制御します。Seekerコンポーネントは、移動スクリプトによって制御されます。移動スクリプトが経路を計算するように指示すると、Seeker は移動し、後で(おそらく後のフレームで)その結果を移動スクリプトに返します。

AstarPathコンポーネントは、シーン内のすべてのグラフデータを保持します。シングルトンパターンに従っているので、このようなコンポーネントは1つのシーンに1つだけ存在する必要があります。このコンポーネントには、1つまたは複数のグラフが含まれ、同じまたは異なるタイプのグラフが含まれます。各グラフは順番に、すべてのノードを含み、管理します(その数は多く、時には数百万に達することもあります)。

このパッケージには、いくつかの動作スクリプトが含まれています(AIPath、RichAI、AILerpなど)。付属のスクリプトを使うこともできますし、自分で書くこともできます (Writing a movement scriptを参照してください)。組み込みの動作スクリプトの比較はこちらでご覧いただけます。
ムーブメントスクリプト

ビデオチュートリアル

テキストチュートリアルではなく、ビデオチュートリアルをお望みなら。このビデオは、そんなあなたのためにあります。ビデオチュートリアルでは、よりハイレベルなアプローチをとっており、カスタムスクリプトを書く代わりに、ビルトインのムーブメントスクリプトを使用する方法を学びます。ビデオチュートリアルとテキストチュートリアルの内容は若干異なるので、両方見てみるのも悪くないでしょう。

また、Gabriel Williams (Unity Cookie) によるタワーディフェンスゲームの作成に関するシリーズ第8部の素晴らしいチュートリアルもご覧ください。

このビデオは、テキストチュートリアルで説明されるほとんどのことをカバーしています。

新規シーン

新しいシーンを作成し、「PathfindingTest」と名付けます。では、AIが歩けるものと避けられるものを作りましょう。シーンに平面を追加して、シーンの原点 (0,0,0) に置き、10,10,10に拡大縮小します。

新しいレイヤ(編集 → プロジェクト設定 → タグ)を「地面」という名前で作成し、そのレイヤに平面を配置します。次に、異なるスケールの立方体をいくつか作成して、平面上に配置します。これらは、AIが避けるべき障害物になります。これらを、「Obstacles」という名前の新しいレイヤに配置します。

これで、あなたのシーンは次のようになります。

A*の追加

これで、AI が立つための地面と、避けるための障害物ができました。そこで、A* Pathfinding System をシーンに追加し、Pathfinding を使えるようにします。

新しいGameObjectを作成し、「A*」という名前を付け、「AstarPath」コンポーネントを追加します(メニューバー→コンポーネント→Pathfinding→Pathfinder)。

AstarPathインスペクタはいくつかのパーツに分かれています。最も重要なのは、「グラフ」エリアと下部の「スキャン」ボタンの2つです。グラフエリアには、シーン内のすべてのグラフが入ります。最大256個まで可能ですが、通常は1つか2つで十分でしょう。通常は、シンプルにするために1つのグラフが好まれます。

グラフエリアをクリックして開くと、追加可能なグラフのリストが表示されます。このチュートリアルでは、グリッドパターンにノードを生成するGridGraphを作成します。
こちらもチェック
グラフの種類については、グラフの種類で詳しく説明しています。

グリッドグラフを追加したら、そのラベルをクリックしてグラフの設定を表示させます。

インスペクタの一番下に、「スキャン」というボタンがあります。これは、その設定とワールドに基づいてグラフを計算するために使用されます。何か設定を変更したら、その変更を確認するためにグラフをスキャンする必要があります。これには便利なショートカットがあります。Cmd+Alt+S (mac) または Ctrl+Alt+S (windows)です。

すべてのグラフは、デフォルトでゲーム起動時にスキャンされます(起動時にキャッシュされている場合を除く、これについては別の部分で説明します)。



GridGraph は、その名の通り、幅*深さのサイズを持つノードのグリッドを生成します。グリッドは、シーンのどこにでも配置することができ、好きなように回転させることができます。

Node Size 変数は、グリッド内の正方形/ノードの大きさを決定します。このチュートリアルでは、1 のままにしておくと、ノードは 1 単位の間隔になります。

ただし、位置は変更する必要があります。位置フィールドの右側にある小さなセレクタで左下に切り替え、(-50,-0.1,-50)を入力してください。0.1 は浮動小数点エラーを避けるためです。このシーンでは、地面が Y=0 にあるため、グラフの位置が Y=0 になっていると、たとえば、高さチェックが行うように、それに対して光線を投射すると、浮動小数点エラーに悩まされる可能性があるからです。

グリッドをシーンに適合させるために、width と depth 変数を変更する必要があり、この場合、両方を 100 に設定します。シーンビューの白い外接矩形によって、グリッドが正しく配置されていることがわかりますが、これで平面を正確に囲んでいるはずです。
Height Testing
ノードを正しい高さに配置するために、A*システムはシーンに対して大量の光線を発射し、どこに当たるかを確認します。それが Height Testing の設定です。光線はグリッドの上の [Ray Length] 単位から下に向かって発射され、ノードはそれがヒットした場所に配置されます。何もヒットしない場合、Unwalkable When No Ground 変数がトグルされていればそのノードは歩けなくなり、false に設定されていればノードはグリッドに対して Y=0 に配置されます。

高さテストが正しいものをヒットするようにするには、使用するマスクを変更する必要があります。現在は、すべてを含んでいますが、これでは障害物も含まれてしまうので、そうしたくありません。そこで、先ほど作成した「地面」レイヤーのみを含むようにマスクを設定します。
Collision Testing
ノードが配置されると、歩行可能かどうかがチェックされます。これは球体、カプセル、または光線によって行われます。通常は、ワールドを歩き回るAIキャラクターと同じ直径と高さのカプセルを使いますが、できれば少し余裕を持たせておくとよいでしょう。

このAIは、標準的な直径と高さがそれぞれ1、2ワールドユニットですが、衝突テストのために直径と高さを2、2に設定し、ある程度の余裕を持たせることにします。

次に、配置した障害物をシステムに認識させるために、衝突テストのマスクを変更する必要があります。今回は、地面を障害物として扱わせたくないので、「障害物」レイヤーのみを含むように設定します。

これですべてが正しく設定されたので、スキャンボタンを押すことができます。ほんの少し待つと、グリッドが生成されます! (すべて正しく設定されていればの話ですが) 下の画像と設定を見比べて、Show Graphsがtrueになっていることを確認してください)。


AIを追加する

動くものがない経路探索のテストってなんだろう?それでは、AIを追加して遊んでみましょう。

カプセルを作成し、キャラクターコントローラコンポーネントを追加します。

このスクリプトは、他のスクリプトからパスを要求するためのヘルパースクリプトで、パスを滑らかにしたり、レイキャストを使用してパスを単純化するなどのパスモディファイアを処理することも可能です。

現在、2つの選択肢があります。自分で移動スクリプトを書くか、ビルトインの移動スクリプトの一つを使うかです。内蔵されたスクリプトは、以下のリンク先のチュートリアルで書くものよりもずっと高度なので、ほとんどの場合、それを使うことをお勧めします。しかし、組み込みのスクリプトを使用する場合でも、カスタム動作スクリプトを書くためのチュートリアルに従うことをお勧めします。

チュートリアルは、このサブページをご覧ください。移動スクリプトの書き方

同梱されているスクリプトは、AIPath、RichAI、AILerpと呼ばれています。AIPathとAILerpはどんなグラフにも使えるスクリプトで、RichAIは主にnavmeshベースのグラフ向けです。AIPathとRichAIスクリプトはゆるやかにパスをたどりますが、AILerpスクリプトは補間を使って非常に正確にパスをたどりますが、おそらく最もリアルな方法ではないでしょう。どちらを使うかは、ゲームによって異なります。
こちらもチェック
付属のムーブメントスクリプトの詳細については、ムーブメントスクリプトを参照してください。また、収録されているサンプルシーンで、どのように使用されているかを見ることができます。

このチュートリアルでは、AIPathコンポーネントをAIにアタッチします。また、「Target」という名前の新しいGameObjectを作成し、AIに移動してほしい場所に配置します。次に、AIDestinationSetterコンポーネントをAIにアタッチします。このコンポーネントは、AIPathスクリプトに特定の場所に移動するように指示する、非常にシンプルなヘルパースクリプトです。将来的には、このスクリプトをゲームに特化したスクリプトに置き換えることになるでしょう。AIDestinationSetterコンポーネントには、"target "というフィールドが1つあり、このフィールドに先ほど作成した "Target "というGameObjectを代入してください。

今、再生ボタンを押すと、AIはターゲットに移動するはずです。移動スクリプトの仕組みや設定方法は、上のリンク先のビデオチュートリアルで詳しく説明しています。うまくいかない場合は、こちらもご覧ください。

スムージング

さて、簡単なグリッドグラフの設定方法とパスの計算方法を学びました。パスファインディングですが、これらのパスをもう少し滑らかに見せる方法があるはずです。
もちろんあります。パスのスムージングや簡略化のスクリプトは Path Modifiers と呼ばれ、Seeker と同じ GameObject に追加できるスクリプトです。

最もわかりやすいのはSimple Smoothモディファイアで、メニューバー → Components → Pathfinding → Modifiers → Simple Smoothで見つけることができます。これをAIに追加します。

このモディファイアが行うことは、各セグメントが最大セグメント長変数よりも小さくなるまで、パスを何度も細分化することです。そして、ポイントを互いに近づけることによって、パスを滑らかにします。このモディファイアには多くの設定がありますが、ここではそのすべてを説明することはしません。各変数の詳細については、SimpleSmoothModifierのドキュメントを参照してください。このチュートリアルでは、Max Segment Lengthを例えば1に設定します。Iterationsは5、Strengthは0.25に設定します。良い値が得られるよう、いろいろ試してみてください。

もう一度再生ボタンを押すと、思い通りにパスが滑らかになっているはずです。
警告
スムーサーは通常、ワールドのジオメトリやグラフを考慮しないので、スムーサーをかけすぎると、歩けない場所をパスが通過してしまう可能性があるので注意が必要です。

もう一つの良いモディファイアはFunnelModifierで、これはパスを非常に単純化します。このモディファイアは、navmesh/recastグラフを使用するときにほとんど使用されます。

モディファイアについて詳しくは、モディファイアを使うのページでご覧ください。

ログの設定

システムによってパスが計算されるたびに、オプションでコンソールにログを記録することができます。これはシステムが何を行っているかを理解する上で大きな助けとなり、またパフォーマンスの問題を発見する上でも役立ちます。しかし、ログは無料ではないので、リリースビルドでは、ログを無効にすることをお勧めします。

ログの設定は A* Inspector → Settings → Debug タブで変更することができます。



パフォーマンスを向上させるため(少し)、またはコンソールのスパムを取り除くために、デバッグを少なくしてください。パスファインディングスクリプトが何をしているのか、より多くの情報を得たい場合は、より多くのデバッグ(重い)を使用します。InGameオプションは、ゲーム内のGUIを使用して最新のパスログを表示します。

まとめ

以上、「チュートリアルを始める」その1でした。何かを学んでいただけたでしょうか?ここから先は、他のドキュメントを読むこともできますし、プロジェクトに直接参加することもできます。もし、もう少し優れたAIが必要なら、プロジェクトに含まれるAIPathスクリプトを使用することができます。

次のチュートリアルでは、navmeshのグラフを使います。ナブメッシュの使用

また、サイドバーにはパッケージの使い方のチュートリアルがたくさんありますので、そちらもご覧ください。

ではまた。

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

編集にはIDが必要です