概要
Unreal Engine の ナビゲーション システム によって、人工知能 (AI) エージェントにパス検索能力が与えられます。スタート位置から目的地までのパス検索を可能にするために、ワールドのコリジョン ジオメトリからナビゲーション メッシュが生成されます。
ナビゲーション メッシュのローカライズされた部分を再ビルドできるよう、デフォルト設定によってナビゲーション メッシュはタイルに細分化されます。最終的なメッシュはポリゴンで構成され、各ポリゴンにはコストが割り当てられます。パス検索アルゴリズムでは、最適なパスを決定する際に、目的地までのコストが最も小さいパスを決定しようと試みます。
ナビゲーション システムには、ナビゲーション メッシュの生成方法を変更できるさまざまなコンポーネントや設定が用意されています。変更できる内容としては、ポリゴンに割り当てられるコストなどがあり、これはエージェントがレベルを移動する方法に影響を与えます。
目標
このクイック スタート ガイドでは、ランタイム時にナビゲーションに影響を与える ナビゲーション モディファイア ボリューム 、 ナビゲーション プロキシ リンク 、ブループリント アクタを使用してナビゲーション メッシュを変更する方法を学習します。
目的
ナビゲーション モディファイア ボリュームを使用して、特定の領域のナビゲーション メッシュ コストを変更する
ナビゲーション プロキシ リンクを使用して、相互にアクセス不可能な 2 つの領域間の接続を作成する
スマート プロキシ リンクを使用してゴールに向かうプラットフォーム間をエージェントがジャンプできるようにする
移動するブループリント アクタを作成してランタイム時にナビゲーション メッシュを動的に再生成する方法を学習する
1 - 必要な設定
「ナビゲーション システムの変更準備ガイド」に従うか、完全なサンプル プロジェクト をダウンロードして、LevelModNavigation_0 レベルを開いてから次のセクションに進みます。
2 - ナビゲーション モディファイア ボリュームを使用する
ナビゲーション モディファイア ボリューム は、ボリューム形状を使用してナビゲーション領域クラスをナビゲーション メッシュに適用します。これを使用して、ボリューム形状内のポリゴンのプロパティを変更し、トラバースのコストを変更できます。
ポリゴンのプロパティは、ナビゲーション モディファイア ボリュームの該当する 領域クラス で定義されます。このクラスは、ナビゲーション メッシュへの効果を決定します。この組み込みクラスを使用して、メッシュを変更したり、独自のカスタム実装を作成したりできます。
これから、この組み込みクラスを使用して、レベル内のナビゲーション メッシュの変更を始めます。
[Place Actors (アクタを配置)] パネルに移動して「 Nav Modifier Volume」を検索します。[Nav Modifier Volume] アクタをレベルにドラッグします。デフォルトでは、ボリューム内にはナビゲーション メッシュが生成されないことに注意してください。
以下に示すように、ボリュームを 移動 して、領域を覆うように 拡大 します。アクタがどのようにレベルの左側に配置されたボリュームの周りを移動して下部の スフィア に到達するかに注目してください。この領域はエージェントがゲーム内で通り抜けることのできない障害にすることができます。
上記の手順を繰り返して、マップの反対側にもう 1 つ領域を作成します。ボリュームを拡大する際に、その両端にエージェントが移動できる空間を残します。
レベルにもう 1 つ [Nav Modifier Volume] をドラッグします。[Details (詳細)] パネルに移動し、 [Area Class (領域クラス)] の隣のドロップダウンをクリックします。リストから [NavArea_Obstacle] クラスを選択します。この組み込みクラスは、ボリューム内の領域にデフォルト値 (緑の NavArea_Default) よりも高いナビゲーション コストを割り当てます。これにより、この領域を経由して目的地に向かうよりも低コストのパスが他に見つからない場合を除いて、エージェントがこの領域を避けるようになります。
このボリュームを 2 回複製して、スフィアの周辺に以下の形状を作成します。これで、エージェントはボリュームを迂回してスフィアに到達するようになります。
もう 1 つボリュームを追加してスフィアの周辺を完全にブロックしてしまっても、エージェントは目的地に到達することができます。というのも、これらのボリュームは有効なパスであるからです。一方、ボリュームの [Area Class] を [NavArea_Null] に変更すると、エージェントはターゲットへの適切なパスを見付けられなくなり、目的地に到達できなくなります。これは、NavArea_Null によって無限のコストが適用され、影響を受ける領域にナビゲーション メッシュが生成されないからです。
[Simulate (シミュレート)] をクリックして、エージェントがスフィア間をどのように移動するのかに注目します。これで、設定変更によりナビゲーション メッシュの生成方法がどのように影響を受けたのかがわかります。
このセクションの結果
このセクションでは、 ナビ モディファイア ボリューム を使用して、ナビゲーション メッシュの生成方法を変更する方法を学びました。また、Unreal Engine のいくつかの組み込み領域クラスについても学びました。
利用可能なナビ モディファイア ボリューム領域クラス
領域クラス |
説明 |
---|---|
NavArea_Default |
デフォルトで、ボリューム内の領域とナビゲーション メッシュに同じナビゲーション コストを割り当てる。 |
NavArea_LowHeight |
エージェントがトラバースできない、低い高さのトラバーサルの条件に一致する領域を表す。ナビゲーション メッシュは、このボリューム内にはナビゲーション データを生成しない。 |
NavArea_Null |
ボリューム内の空の領域を表す。ナビゲーション メッシュは、このボリューム内にはナビゲーション データを生成しない。 |
NavArea_Obstacle |
ボリューム内の領域に高いナビゲーション コストを割り当てる。 |
3 - ナビゲーション リンク プロキシを使用する
ナビゲーション リンク プロキシ は、直接的なナビゲーション パスのない 2 つのナビゲーション メッシュ領域を接続します。ナビゲーション リンク プロキシは、パスの検索中に、エージェントが目的地に到達できる追加の連結部分として使用されます。
ナビゲーション リンク プロキシの一般的な用途は、個別のナビゲーション メッシュを持つ領域の間に橋を構築し、連続したナビゲーション パスを利用できないときにゴールに向かってプラットフォームから落下したり、ジャンプしたりするようにエージェントに指示することです。
橋を作成して 2 つの領域を繋ぐ
1 つ目の ナビ モディファイア ボリューム を選択して、以下のようにフロアの全長を覆うようにサイズ変更します。これで、エージェントがレベル下部のスフィアに到達できなくなります。
[Place Actors] パネルに移動して、 [Cube (キューブ)] アクタをレベルにドラッグします。以下のように、[Scale (拡大・縮小)] で X = 4、Y = 1、Z = 0.2 に設定して、配置します。
この キューブ を複製して、以下のようにレベルの反対側に移動します。
これらのキューブ アクタは、レベルのナビゲーション リンク プロキシを視覚的に表す役割を果たします。これらをナビゲーション リンク プロキシと連結して使用する必要はありません。
[Place Actors (アクタを配置)] パネルに移動して「 Nav Link Proxy 」を検索します。[Nav Link Proxy] アクタをレベルにドラッグします。
Nav Link Proxy を選択して、PointLinks[0].Left ハンドルをクリックし、メッシュの片側に配置されるように動かします。[PointLinks[0].Right] ハンドルをクリックし、以下のように、メッシュのもう一方の側にくるように移動します。
Nav Link Proxy によってナビゲーション メッシュのサーフェスが接続されていない場合、緑色の矢印は表示されなくなります。
接続を作成したので、経路にナビゲーション データが存在していなくても、エージェントが Nav Link Proxy を経由して移動できるようになりました。
Nav Link Proxy を選択した状態で [Details] パネルに移動し、 [Point Links (ポイント リンク)] の下の「 0 」というラベルのセクションを展開して [Direction (方向)] ドロップダウンを見付けます。[Direction] は、 [Both Ways (双方向)] 、 [Left to Right (左から右)] 、 [Right to Left (右から左)] のいずれかを選択できます。この例では、 [Left to Right] を選択します。
Nav Link Proxy を複製して、レベルの反対側に移動します。この例では、 [Direction] を [Right to Left] に設定します。
[Simulate] をクリックして、今度はエージェントが左から入り、右から出るようにスフィアに到達することに注目します。
このセクションの結果
Nav Link Proxy を使用して、移動可能なパスのない 2 つの ナビゲーション メッシュ 領域を接続しました。また、Nav Link Proxies に [Both Ways] 、 [Left to Right] 、 [Right to Left] などのさまざまな方向を設定しました。
Nav Link Proxy を使用してエージェントがプラットフォームから落下できるようにする
もう 1 つ Nav Link Proxy をレベルにドラッグして、以下のように、高くなっているプラットフォームの端に配置します。
[PointLinks[0].Left] を選択して、プラットフォームの端に配置し、[PointLinks[0].Right] を選択してフロアにオーバーラップするように下部に配置します。
[Details] パネルに移動して、 [Point Links] の「 0 」というラベルのセクションを展開し、 [Direction] を [Left to Right] に設定します。
[Simulate] をクリックして、エージェントがプラットフォームから飛び降りてゴールに到達する様子に注目します。
このセクションの結果
このセクションでは Nav Link Proxy を使用してエージェントがプラットフォームから飛び降りてゴールに到達できるようにしました。
Nav Link Proxy を使用してエージェントがゴールにジャンプできるようにする
このセクションでは、 Nav Link Proxy の スマート リンク を使用して、エージェントがプラットフォームからプラットフォームにジャンプできるようにする方法を学習します。
プラットフォーム メッシュを選択し、 Alt キーを押した状態で横にドラッグして複製します。
以下のように、新しいプラットフォームのサイズを変更して、高い位置に移動します。
スフィア アクタを複製して、プラットフォームの上に配置します。
コンテンツ ドロワー 内で右クリックして、 [Create Basic Asset (基本アセットを作成)] セクションの [Blueprint Class (ブループリント クラス)] を選択します。
[Pick Parent Class (親クラスを選択)] ウィンドウで [All Classes (すべてのクラス)] セクションに行き、矢印を展開します。「 Nav Link Proxy 」を検索して、 [Select (選択)] をクリックします。ブループリントに「 BP_NavProxyLink 」という名前を付けます。
[BP_NavProxyLink] をダブルクリックして開きます。イベント グラフ 内でダブルクリックして、「 Event Receive Smart Link Reached 」を検索、選択します。
Event Receive Smart Link Reached ノードの Agent ピンをドラッグして、「 Cast to Character 」を検索、選択します。
Cast to Character ノードの As Character ピンをドラッグして、 [Promote to variable (変数へ昇格)] を選択します。
As Character ノードの execution ピンをドラッグして、「 Suggest Projectile Velocity Custom Arc 」を検索、選択します。
As Character ノードの 青色 のピンをドラッグして、「 Get Actor Location 」を検索、選択します。Get Actor Location ノードの Return Value ピンを SuggestProjectileVelocityCustomArc ノードの Start Pos ピンに接続します。
Event Receive Smart Link Reached ノードの Destination ピンをドラッグして SuggestProjectileVelocityCustomArc ノードの End Pos ピンに接続します。
As Character 変数を イベント グラフ にドラッグして、 [Get As Character (As Character を取得)] を選択します。このノードからドラッグして「 Launch Character 」を検索、選択します。[XYOverride] チェックボックスと [ZOverride] チェックボックスをオンにします。
SuggestProjectileVelocityCustomArc ノードからドラッグして「 Delay 」を検索、選択します。[Duration (期間)] を 0.1 に設定します。Delay ノードの Completed ピンを Launch Character ノードに接続します。
SuggestProjectileVelocityCustomArc ノードの Out Launch Velocity ピンをドラッグし、「vector * float」を検索、選択します。
Multiplication ノードの 黄色 のピンを Launch Character ノードの Launch Velocity ピンに接続します。Multiplication ノードの 緑色 のピンを右クリックして [Promote to variable] を選択します。
New Var 0 ノードを選択した状態で [Details] パネルに行き、変数の名前を「 JumpBoost 」に変更します。デフォルト値を 1 に設定します。以下のように、 [Instance Editable (インスタンス編集可能)] チェックボックスをオンにします。
ブループリントを コンパイル して 保存 します。
レベル内の BP_NPC_ModNavMesh キャラクターを選択して、 [Details] パネルで [Target List] の隣の 追加 (+) ボタン をクリックして新しいエントリを追加します。プラットフォームに追加した最後の スフィア アクタを検索、選択します。
以下のように、 [BP_NavProxyLink] ブループリント アクタをプラットフォームにドラッグして接続を調整します。
[BP_NavProxyLink] ブループリント アクタを選択した状態で [Details] パネルに移動し、 [Copy End Points from Simple Link to Smart Link (シンプル リンクからスマート リンクにエンド ポイントをコピー)] ボタンをクリックします。[Smart Link Is Relevant (スマート リンクが関連している)] チェックボックスをオンにします。
[Simulate] をクリックして、エージェントがジャンプして最後のスフィアに到達する様子を観察します。
Nav Link Proxy は、隣接するナビゲーション メッシュ タイルしか接続できません。RecastNavMesh-Default アクタを選択して [Draw Tile Bounds (タイルの境界を描画)] チェックボックスをオンにすると、タイルを視覚化できます。
このセクションの結果
このセクションでは、カスタム Nav Proxy Link ブループリントを作成する方法と、それを使用してエージェントをプラットフォームにジャンプさせる方法を学習しました。
4 - ランタイム時にナビゲーション メッシュを生成する
Unreal Engine には以下の 3 つのナビゲーション メッシュ生成モードがあります。
生成モード |
説明 |
---|---|
Static (スタティック) |
ナビゲーション メッシュはオフラインで生成され、レベルと一緒に保存されます。ナビゲーション メッシュはランタイム時にロードされ、変更できません。 |
Dynamic (ダイナミック) |
ナビゲーション メッシュはオフラインで生成され、レベルと一緒に保存されるか、ランタイム時にビルドされます。ランタイム時に、ナビゲーション メッシュで使用されるナビゲーション関連データを更新でき、データ変更に影響されるタイルで生成が行われます。 |
Dynamic Modifiers Only (ダイナミック モディファイアのみ) |
ナビゲーション メッシュはオフラインで生成され、レベルと一緒に保存されます。ランタイム時に、ナビゲーション領域、ナビゲーション リンク、動的オブジェクトなど、ナビゲーション モディファイアのみが、コストやブロック領域を変更して既存のナビゲーション メッシュを変更できます。ランタイム時に、新しいナビゲーション メッシュ サーフェスは生成されません。 この手法では、ナビゲーション メッシュがコリジョン データをキャッシュできるので、影響を受けるタイルの処理コストが最大で 50% 少なくなります。 上級ユーザーは、このメリットと制限事項をよく考慮してこのモードを使用することをお勧めします。 |
デフォルトで、ナビゲーション メッシュは [Static] に設定されています。しかし、ランタイム時に変更できるように、ナビゲーション メッシュ生成をいずれかのダイナミック モードに設定できます。
ランタイム生成 (Dynamic Modifiers Only) を使用
[Runtime Generation (ランタイム生成)] 設定を変更するには、メニュー バーの [Settings (設定)] > [Project Settings (プロジェクト設定)] に移動します。
[Navigation Mesh (ナビゲーション メッシュ)] 設定の [Runtime (ランタイム)] セクションに移動し、 [Runtime Generation] ドロップダウンをクリックします。この例では、 [Dynamic Modifiers Only] を選択します。
コンテンツ ブラウザ 内で右クリックして、 [Create Basic Asset] セクションの [Blueprint Class] を選択します。
[Common Classes (よく使うクラス)] セクションの [Actor (アクタ)] クラスを選択します。ブループリントに「 BP_RotatingActor 」という名前を付けます。
BP_RotatingActor ブループリントをダブルクリックして開きます。[+Add] ドロップダウンをクリックし、「Cube」を検索、追加します。キューブを [Scale (拡大・縮小)] で X = 4、Y = 1.5、Z = 1 に設定します。
[Add Component] ドロップダウンをクリックして、「Rotating Movement」を検索、選択します。
ブループリントを コンパイル して、保存 します。
[BP_RotatingActor] ブループリント アクタをレベルにドラッグして、 [Simulate] をクリックします。回転するメッシュでナビゲーション メッシュが更新されない様子に注目します。これは、 [Dynamic Modifier Only] ランタイム生成モードが機能するのは、アクタが NavModifier コンポーネントを持つ場合だけだからです。
[BP_RotatingActor] ブループリントに戻り、 [Add Component] ドロップダウンをクリックします。「Nav Modifier」を検索して選択します。
ブループリントを コンパイル して、保存 します。[Simulate] をクリックして違いを確認します。今度は、レベル内でのメッシュの回転に合わせて、ナビゲーション メッシュが正しく更新されます。
レベル内で新しいナビゲーション メッシュが生成されない様子に注目します (生成されるタイルは赤色で表示されます)。ナビゲーション モディファイアは単に既存のナビゲーション メッシュを変更します。
このセクションの結果
このセクションでは、ゲームプレイ中にランタイム生成モード [Dynamic Modifiers Only] を使用してナビゲーション メッシュを再生成する方法を学習しました。また、NavModifier コンポーネントを持つ単純な回転するブループリント アクタを使用して結果をテストしました。
ランタイム生成 (Dynamic) を使用
コンテンツ ドロワー 内で右クリックして、 [Create Basic Asset (基本アセットを作成)] セクションの [Blueprint Class (ブループリント クラス)] を選択します。
[Common Classes (よく使うクラス)] セクションの [Actor (アクタ)] クラスを選択します。ブループリントに「BP_MovingActor」という名前を付けます。
BP_MovingActor ブループリントをダブルクリックして開きます。[+Add] ドロップダウンをクリックし、「Sphere」を検索、追加します。スフィアを [Scale] で X = 2、Y = 2、Z = 2 に設定します。
イベント グラフ 内で右クリックして、「Add Custom Event」を検索、選択します。イベントに「MoveForward」という名前を付けます。これらの手順を繰り返し、もう 1 つイベントを作成して「MoveBackwards」という名前にします。
MoveForward ノードからドラッグして、「Add Timeline」を検索、選択します。タイムラインの名前を「TM_MoveObject」にします。MoveBackwards ノードを TM_MoveObject ノードの Reverse ピンに接続します。
TM_MoveObject ノードをダブルクリックして開きます。[Add Float Track (浮動小数トラックを追加)] ボタンをクリックして、新しい浮動小数トラックを作成します。トラックに「Alpha」という名前を付けます。
グラフ内を右クリックして、 [Add key to CurveFloat_1 (CurveFloat_1 にキーを追加する)] を選択します。Time = 0 、Value = 0 と入力します。
前の手順を繰り返し、Time = 5 、Value = 1 と入力します。
スフィア コンポーネントを イベント グラフ までドラッグし、ノードを作成します。スフィア ノードからドラッグして、「Set Relative Location」を検索、選択します。
TM_MoveObject ノードの Update ピンを SetRelativeLocation ノードに接続します。SetRelativeLocation ノードの New Location ピンを右クリックして [Split Struct Pin (構造体ピンを分割)] を選択します。
SetRelativeLocation ノードの New Location X ピンをドラッグし、「 Lerp 」を検索、選択します。TM_MoveObject の Alpha ピンを Lerp ノードの Alpha ピンに接続します。
Lerp ノードの B ピンを右クリックして [Promote to Variable] を選択します。[Details] パネルに移動して、変数に「 Distance 」という名前を付けます。[Instance Editable (インスタンス編集可能)] チェックボックスをオンにします。
ブループリント を コンパイル して 保存 します。[Distance] のデフォルト値を 1000 に設定します。
TM_MoveObject タイムラインの Finished ピンをドラッグして、「 Delay 」を検索、選択します。[Duration] を 1 に設定します。
Delay ノードの Completed ピンからドラッグし、「Branch」を検索して選択します。
Branch ノードの Condition ピンを右クリックして、 [Promote to Variable] を選択します。[Details] パネルに移動し、変数の名前を「Forward」に変更します。
Forward 変数を イベント グラフ にドラッグし、 [Set Forward] を選択します。Branch ノードの True ピンを Set Forward ノードに接続します。Set Forward ノードからドラッグして、「Move Backwards」を検索、選択します。
Forward 変数を イベント グラフ にドラッグし、 [Set Forward] を選択します。Branch ノードの False ピンを Set Forward ノードに接続します。Set Forward ノードの [Forward] チェックボックスを オン にします。Set Forward ノードからドラッグして、「Move Forward」を検索、選択します。
イベント グラフ を右クリックして、「Event Begin Play」を検索、選択します。Event Begin Play ノードからドラッグして、「Move Forward」を検索、選択します。
ブループリントを コンパイル して 保存 します。完成したブループリントは以下のとおりです。
[BP_MovingActor] ブループリント アクタをレベルにドラッグして、 [Simulate] をクリックします。アクタの動きでナビゲーション メッシュが更新されない様子に注目します。
[Settings] > [Project Settings] の順にクリックして [Navigation Mesh] 設定に移動します。
[Runtime] セクションで [Runtime Generation] ドロップダウンをクリックして [Dynamic] を選択します。
レベルに戻り、 [Simulate] をクリックします。今度はナビゲーション メッシュが正しく更新されます。
このセクションで使用されている例では、実行時にコンスタントに計算コストの高いナビゲーション メッシュが強制生成されます。これらの例はデモンストレーション目的でのみ使用されています。ベストプラクティスではありません。
このセクションの結果
このセクションでは、ゲームプレイ中にランタイム生成設定 [Dynamic] を使用してナビゲーション メッシュを再作成できることを学習しました。また、レベル内のスフィア メッシュを動かし、絶えずナビゲーション メッシュ再生成を強制するブループリントを作成して、結果をテストしました。