このチュートリアルのパートでは、プレイヤーを検知し、追跡し、ダメージを与える敵 NPC を作成します。 さらに、敵はダメージを受けたり、ナビゲーション メッシュを使用して環境内を移動して障害物を避けることができます。
これまでのチュートリアルと同様に、まずブループリント ビジュアル スクリプティングを使用して敵のロジックを作成します。 次に、ナビゲーション メッシュを作成して、AI コントローラーが保有しているキャラクターが移動できるゾーンを定義します。
開始する前に
「パズル アドベンチャーの設計」の以前のセクションで取り上げた、これらのトピックを理解できていることを確認します。
ブループリントとブループリント関数
キーの作成には、次のアセットが必要になります。
BPL_FPGameブループリント関数ライブラリ
敵のナビゲーションに NavMesh を作成する
敵をレベルに追加してプレイヤーを追跡させる前に、Enemy AI がレベルを移動するために使用する NavMesh をビルドする必要があります。
NavMesh は「Navigation Mesh (ナビゲーション メッシュ)」の略で、AI がナビゲートできるレベル上の領域を定義します。 このチュートリアルで NavMesh を作成することで、敵がプレイヤーを追うために移動できるゾーンを定義します。
レベルにナビゲーション メッシュを追加するには、次の手順を実行します。
Unreal Editor のレベル エディタで、メイン ツールバーで [Create (作成)] ボタンをクリックし、[Volumes (ボリューム)] に移動して [Nav Mesh Bounds Volume (ナビメッシュ バウンズ ボリューム)] を選択します。 これにより、プロジェクトで AI にナビゲート可能なゾーンが作成されます。
トランスフォーム ツールを使用して、NavMesh を移動し、レベル内の床と交差させてください。
キーボードの P キーを押してデバッグ ビューに切り替えます これを使用すると、レベル ビューポートで NavMesh の詳細 (レベル上のナビゲート可能なゾーン、レベル ビューポートの左側のテキストベースのデバッグ情報など) を表示することができます。
デバッグ情報に「NavMesh Needs To Be Rebuilt (NavMesh は再ビルドが必要です)」というメッセージが表示された場合は、メニュー バーの [Build (ビルド)] > [Build Paths (ビルド パス)] を選択します。 これにより、NavMesh がリビルドされます。
さらに、NavMesh の移動やスケール (キーボードの W および R キー) を行って、NavMesh のバウンドを変更することができます。 このボリュームは好みに合わせてスケールできます。
NavMesh の最下部がへこんだ床ピースを含めるのに十分低く、最上部が敵の高さに対して十分高いことを確認してください。
チュートリアルのサンプル レベルを使用している場合、2 つのナビゲーション メッシュ境界ボリュームを作成し、廊下 3 と部屋 3 を埋めるようにスケーリングしてください。
NavMesh をスケールおよび移動すると、キューブのような障害物を含まない場合は、バウンディング ボックスのサイズに合わせて緑色のゾーンが拡大します。 赤で切り取られている部分は、ゲーム内で AI がナビゲートできないことを意味しています。
Unreal エディタによって NavMesh に含まれていない要素が含まれている場合は、そのメッシュ レベル オブジェクトを選択し、詳細パネルの [Can Ever Affect Navigation (ナビゲーションへの影響が許可)] を無効にします。
敵を作成する
Character クラスには、人型の敵に適した移動機能とアニメーション機能がすでに含まれているため、敵は Character クラスから作成してください。 キャラクター クラスはポーンを拡張します。ポーンは、乗り物、カメラ、ヒューマノイド以外のクリーチャーなどに使用される、より一般的な「制御可能なアクタ」です。 人の形をした敵の場合、キャラクターがより良い出発点です。
このキャラクターをゼロから作成しているため、メッシュを追加して敵を視覚的に表現し、アニメーション ブループリントを使用してアニメーションを再生します。 アニメーション ブループリントはプロジェクト ファイルで提供されているため、最初から作成する必要はありませんが、敵キャラクターのブループリントとアニメーション ブループリントを統合する方法を習得することが重要です。
まず、Enemy ブループリントを作成します。 次の手順を実行します。
コンテンツ ブラウザで、[Content (コンテンツ)] > [AdventureGame] > [Designer (デザイナー)] > [Blueprints (ブループリント)] > [Characters (キャラクター)] に移動します。
コンテンツ ブラウザの空いている場所を右クリックし、[Blueprint Class (ブループリント クラス)] をクリックします。
新しいウィンドウで、ベース クラスとして [Character (キャラクター)] を選択します。
このクラスに「
BP_Enemy」という名前を付け、ダブルクリックしてブループリント エディタで開きます。
ブループリント クラスを作成する際には、ビルド元となる親クラスを選択してください。 この親にはすでにビルトイン機能が備わっています たとえば、アクタ クラスからブループリントを作成した場合、トランスフォームと、コンポーネントを保持してロジックを実行する機能から開始することになります。 キャラクター クラスから開始した場合、移動、コリジョン、アニメーション サポートもあります。 基本クラスは、テンプレートと同様に使用します。 機能を追加すると、その基本クラスが拡張されます。
BP_Enemy ブループリントが開いている状態で、Viewport (ビューポート) タブを開いて Components (コンポーネント) パネルを確認します。 リストの一番下に キャラクター移動 (CharMoveComp) コンポーネントがあります。 全てのキャラクター クラスにはキャラクター移動コンポーネントが含まれています。 コンポーネントを選択し、詳細パネルでコンポーネント内の全ての設定を確認します。 プロジェクトで敵を作成すると、これらの設定の一部がオーバーライドされます。
3D モデルを敵に追加する
キャラクターにはメッシュ コンポーネントも含まれていますが、このコンポーネントはスタティック メッシュではなくスケルタル メッシュです。 これまで使用してきたスタティック メッシュは動かない固定の 3D モデルですが、スケルタル メッシュには内部スケルトンがあり、アニメーションや変形が可能です。
まず、キャラクターのメッシュとアニメーションを設定します。 次の手順を実行します。
メッシュ コンポーネントを選択し、詳細パネルを確認してください。 [Mesh (メッシュ)] カテゴリを見つけ、[Skeletal Mesh Asset (スケルタル メッシュ アセット)] の横にあるドロップダウンをクリックします。 リストから「
SKM_Manny_Simple」モデルを検索して選択します。 これにより Manny モデルがブループリントに割り当てられます。詳細 パネルで [Animation (アニメーション)] カテゴリに移動します。[Anim Class (アニメーション クラス)] の横のドロップダウンをクリックして、
ABP_Unarmedアニメーション ブループリントを割り当てます。 これで、敵キャラクターは [Viewport (ビューポート)] タブでアイドル アニメーションを再生しているはずです。アニメーション ブループリントが敵で適切に機能するように変更します。
敵メッシュの Anim Class プロパティで、
ABP_Unarmedの横にある [Browse to Asset in Content Browse (コンテンツ ブラウザにアセットをブラウズ)] をクリックします。ABP_Unarmedアニメーションブループリントをダブルクリックして開きます。Sequence ノードの Then 1 ピンの後に続くロジックのグループに移動します。
敵キャラクターが動くのを妨げる加速度チェックは無効にする必要があるため、And ノードと Set Should Move ノード間のワイヤーを削除します。
Greater than (>) ノードの出力ピンを Should Move ピンに接続し、加速度のチェックをバイパスします。
ブループリントをコンパイルして、保存し、閉じます。
ビューポートでは、敵キャラクターを囲む円柱形カプセル形状が表示されます。 これは、地面を含む他のオブジェクトとのコリジョンを検出するカプセル コンポーネントの視覚的な表現です。 キャラクターのメッシュはより複雑な形状であるため、単純なコリジョン シリンダーを使用して形状をスムージングし、コリジョン検出のパフォーマンスを向上させています。
メッシュはオフセットされており、カプセルに合わせられていません。 キャラクターのメッシュがカプセル コンポーネントに揃うように、キャラクターを下に動かして、足がカプセル コンポーネントの下部に接するようにします。
キャラクター メッシュをそのコリジョン ボリュームに合わせるには、次の手順に従います。
Mesh (メッシュ)コンポーネントを選択し、3D モデルをハイライトします。
詳細パネルで、トランスフォーム カテゴリの [Location (位置)] フィールドを使用して、最後のフィールドの青色の Z 軸 を変更します。 値を
「-96」に設定します。
現在、どちらのコンポーネントも原点の中央に配置されているため、ゲーム内で敵が地面より上に浮くことはありません。
最後に、キャラクターに矢印コンポーネント (Arrow) があることを確認します。 矢印は、ブループリントの正面方向を示しています。 キャラクターが正しい方向に走るように、この矢印がメッシュの向いている方向と一致していることを確認します。
キャラクター メッシュを前方に向くようにするには、次の手順を実行します。
メッシュ コンポーネントを再度選択します。 詳細パネルのギズモ回転または[Transform (トランスフォーム)] カテゴリを使用して、キャラクターを Z 軸で 90 度回転させてください。 その最後の回転値は -90 である必要があります。
3D モデルのマテリアルを変更する
機能の作成に進む前に、敵モデルの色を赤に変更しましょう。 これにより、プレイヤーと区別して、現在の白色ではなく、敵のように見えます。
敵キャラクターを別の色にするには、次の手順に従います。
詳細パネルの [Materials (マテリアル)] セクションに 2 つの要素があるのがわかります。
MI_Manny_01_Newは、上腕、脚、頭部など、敵モデルのさまざまな部分に影響を及ぼすマテリアルです。MI_Manny_02_Newは、前腕と胴体に影響を与えるマテリアルです。
[Element 0] の横にあるフォルダと虫眼鏡のような [Browse in Content Browser (コンテンツ ブラウザでブラウズ)] ボタンをクリックします。 これにより、コンテンツ ブラウザでこのマテリアルを含むフォルダーが開きます。 2つ目のマテリアルの
MI_Manny_02_Newもここにあります。MI_Manny_01_Newアセットを右クリックして、[Create Material Instance (マテリアル インスタンスの作成)] をクリックします。マテリアル インスタンスの名前を
MI_Enemy_01にし、ダブルクリックして開きます。詳細パネルで、01 - BaseColor を展開し、Paint Tint プロパティを有効にします。
[Paint Tint (ペイントの色合い)] プロパティの横にある色見本をクリックし、カラーを選択します。 このチュートリアルでは、Hex sRGB =
F60E6EFFを使用しています。[Save (保存)] をクリックしてウィンドウを閉じます。
コンテンツ ブラウザに戻り、
MI_Manny_02_Newを右クリックして、[Create Material Instance (マテリアル インスタンスを作成)] をクリックします。このマテリアル インスタンスに
「MI_Enemy_02」という名前を付け、前の手順を繰り返してカラーを変更し、アセットを保存します。
上記の手順を繰り返すと、2 つのマテリアル インスタンス「MI_Enemy_01」と「MI_Enemy_02」が作成されます。
次に、これらのマテリアルを敵キャラクターに割り当てるには、次の手順に従います。
BP_Enemyブループリントの詳細パネルで、[Materials (マテリアル)] セクションに進みます。[Element 0] のドロップダウンをクリックして、作成した新しいマテリアル「
MI_Enemy_01」を選択します。[Element 1] はマテリアル「
MI_Enemy_02」に変更します。
レベルに敵を追加する
レベルに敵を追加して、そこまでの敵の外観と動作を確認します。
コンテンツ ブラウザから敵のブループリントをレベル ビューポートにドラッグし、プレイヤーの前に配置します。
ゲームをプレイすると、敵がアイドリング アニメーションでアニメーションするのを確認できるはずです。
ゲームプレイ開始時に敵を設定する
敵の準備ができたので、ゲームプレイ機能を作成できます。 まず、敵がスポーンされたときに必要な敵のプロパティを設定します。
ゲーム開始時に敵の移動速度を設定するには、次の手順を実行します。
BP_Enemyのブループリント エディタ ウィンドウで、[EventGraph (イベント グラフ)] タブに移動します。 デフォルトでは、Event BeginPlay、Event ActorBeginOverlap、および Event Tick という 3 つのイベントが表示されます。 ActorBeginOverlap を選択し、このチュートリアルでは不要であるため削除します。[Components (コンポーネント)] パネルを使用して、[Character Movement (キャラクターの移動)] コンポーネントをイベント グラフにドラッグします。 これにより Character Movement ノードが作成されます。 このコンポーネント ノードを使用すると、グラフから該当するコンポーネントのプロパティを確認または変更できます。
Character Movement ノードのピンをドラッグして、Set Max Walk Speed ノードを作成します。
Set ノードの緑色の Max Walk Speed ピンを右クリックし、[Promote to Variable (変数へ昇格)] を選択します。
[My Blueprint (マイ ブループリント)] パネルで [Variables (変数)] リストに新規変数を作成されます。
変数の名前を
Max Speedにします。 変数の横にある目のアイコンをクリックして、これを編集可能なパブリック変数に設定します。そのカテゴリを [Setup (設定)] に変更します。
ブループリントをコンパイルし、詳細パネルで [Max Speed (最大速度)] のデフォルト値を
「200」に設定します。編集可能な変数には必ずデフォルト値を割り当ててください。 レベル エディタで値を変更するのを忘れてデフォルト値が「0」になっていると、敵は移動できなくなります。
Event BeginPlay を Set Max Walk Speed ノードに接続してください。
次に、2 つの変数で敵のヘルスを追跡します。 TotalHP はインスタンス編集可能変数であり、敵の開始 HP を設定します。 CurrentHP は、プレイヤーや環境によってダメージを受けたときに、ゲームプレイ中で敵が持っているヘルス値を追跡します。
敵の HP を設定するには、次の手順を実行します。
[Variables (変数)] リストで、Float 型の「
CurrentHP」という名前の新しい変数を追加します。[Variables] リストから [CurrentHP] 変数をイベント グラフにドラッグし、[Set Current HP] オプションをクリックします。 Set Max Speed ノードの実行ピンをドラッグし、Set Current HP ノードの実行ピンに接続します。
Set Current HP ノードで、Current HP の浮動小数ピンを右クリックして、Promote to Variable をクリックします。
この変数の名前を「TotalHP」に変更します. その型が Float であることを確認し、その目のアイコンをクリックして、公開し、編集可能にします。 [Details(詳細)]パネルで [Category(カテゴリ)] を[Setup (設定)]に設定します ブループリントをコンパイルし デフォルト値を
「100」に設定します。Set ノード間の実行ピンを接続します。
このイベント グラフではプレイヤー キャラクターに対して多くのアクションを実行します。次はプレイヤーへの参照を変数として保存します。
プレイヤー キャラクターの変数を設定するには、次の手順を実行します。
[Variables (変数)] リストで、「
PlayerRef」という名前の新しい変数を作成し、その型を [Character (Object Reference)] に変更します。プレイヤーを参照する必要があるたびに Get Player Character 機能を呼び出すよりも、キャラクター オブジェクトの参照変数を作成するほうがプロジェクトのパフォーマンスの面で優れています。
Set Current HP ノードの後に、Set PlayerRef ノードを接続します。
そのプレイヤー参照入力ピンで、Get Player Character ノードを接続します。 Player Index の値が 0 であることを確認してください。 これは、レベルにスポーンされた最初のプレイヤー キャラクターのデフォルトのインデックスです。
敵がプレイヤーを追跡するようにする
次に、敵をプレイヤーに向かって移動させるロジックを作成します。 これを行うには、カスタム イベントを作成します。 ブループリント内の任意の場所からカスタム イベントを呼び出し、ロジックをトリガーおよび実行します。
移動アクションをトリガーするカスタム イベントを作成するには、次の手順を実行します。
イベント グラフ内の任意の場所を右クリックして、検索フィールドに
「Custom Event」と入力します。 リストで Add Custom Event オプションをクリックし、このイベントに「MoveToPlayer」という名前を付けます。MoveToPlayer イベント ノードのピンをドラッグし、AI MoveTo ノードを検索して作成します。 このノードは、AI コントローラーを持つポーンが特定の場所に移動するために使用するアクションです。 この場合、敵をプレイヤーに移動させるために使用します。
AI MoveTo ノードで、Pawn ピンをドラッグし、検索フィールドに
「Self」と入力します。 [Get a reference to self] を選択し、ゲーム内でこのブループリントのアクタを参照するノードを作成します。AI MoveTo ノード のターゲッ アクタ ピンをドラッグして、Get PlayerRef ノードを作成します。
[Acceptance Radius (許容半径)] を
10に設定します。 これは、敵が目的地に到達したと判断する距離 (センチメートル単位) です。 [Stop on Overlap (オーバーラップ時に停止)] よりも細かく制御できます。
この場合、Self ノードを使用して、移動する必要があるポーンとしてこの敵を定義します。 次に、プレイヤーをターゲット アクタとして設定します。ターゲット アクタとは、ポーンが向かっていく先となるターゲットです。
AI MoveTo ノードには、On Success イベントと On Fail イベントが付属しています。 これらは、敵がプレイヤーに到達した場合、または失敗した場合の動作を定義します。
敵が移動した後の動作を定義するには、次の手順を実行してください。
AI MoveTo ノードで、On Success ピンをドラッグして、Delay ノードを作成します。
Delay ノードの Duration (期間) ピンを右クリックして、Promote to Variable (変数に昇格) を選択します。
この変数に「WaitAtDestination」という名前を付け、その型を Float にしてください。
ブループリントをコンパイルし、WaitAtDestination のデフォルト値を
5に変更します。 目のアイコンをクリックして編集可能にしカテゴリを [Setup (設定)] に変更します。イベント グラフで Delay ノードの実行ピンをドラッグして、Move To Player ノードを作成します。 これにより、敵はプレイヤーが離れても追跡を続けますが、プレイヤーが距離を取れるよう、追跡開始前にディレイがあります。
AI MoveTo ノードで、On Fail ピンをドラッグして、新しい Delay ノードを作成します。
[Delay (ディレイ)] の Completed ピンをドラッグして、Move To Player ノードを作成します。 [Duration (持続時間)] は 0.2 のままにしてください。 これにより、敵がプレイヤーに到達していない場合でも、敵が動き続けることが保証されます。
Event BeginPlay グループのロジック内です。 このシーケンスの最後に、Set Player Ref ノードの後に Move To Player ノードを接続して、このイベントをトリガーします。 これは、ゲームの開始時に敵を動かし、敵の動きをテストできるようにします。
ブループリントを保存してコンパイルします。
イベント グラフは次のようになります。
敵移動をテストする
レベルで敵アクタが NavMesh のバウンド内にあることを確認します。つまり、緑色のゾーン上にあります。
レベルのビューポートまたはアウトライナーで BP_Enemy アクタを選択する。 詳細パネルでは、ブループリントに追加した変数が [Setup (設定)] セクションに表示されます。 これらの値はプロジェクトのニーズに合わせて変更することができます。また、[Debug Detection (デバッグ検出)] をオンにしてライン トレースのデバッグ描画を有効にすることもできます。
レベルを再度再生し、敵がどのように行動するかを確認してください。 プレイヤーに向かって歩行し、プレイヤーに到達したら停止し、5 秒待機してから、再びプレイヤーに向かって歩行しようとするようになっているはずです。
意図した通りに動かない場合は、ブループリントで作成した変数に、シーンの BP_Enemy で設定された値が正しいかどうかをチェックしてください。 最大速度または最大検出距離の値を設定しない場合、敵は動きません。 値が小さすぎる場合も 同じことが起こることがあります。
プレイヤーにダメージを与える
これで敵がプレイヤーに到達できるようになったので、敵がプレイヤーに衝突したときにダメージを与える機能を追加できます。 このチュートリアルでは、プレイヤーと接触すると自己破壊する敵を作成するため、プレイヤーにダメージを与えた後にその敵を排除するロジックも追加します。
敵がプレイヤーと衝突したかどうかをチェックするには、次の手順に従います。
[Components (コンポーネント)] パネルで、[Capsule Component (CollisionCylinder) (カプセル コンポーネント (CollisionCylinder))] を右クリックし、[Add Event (イベントを追加)] に移動し、[Add OnComponentHit (OnComponentHit を追加)] を選択してください。
これにより、イベント グラフに新しいイベント ノードが作成され、Capsule コンポーネントが何かにヒットしたときに実行されます。
On Component Hit ノードのピンをドラッグし、Branch ノードを作成します。
On Component Hit ノードの Other Actor ピンに Condition ピンを接続すると、新しいノードの作成を促すプロンプトが表示されます。
Equal ノードを作成します。 Equal ノードの Select Asset ピンをドラッグし、PlayerRef 変数への参照を追加します。
このロジックにより、敵の Capsule コンポーネントがゲーム内で何かにヒットしたときにイベントがトリガーされます。 このイベントは、カプセル コンポーネントがプレイヤー キャラクターにヒットしたかどうかをチェックします。
プレイヤーに 1 ヒット分のダメージを与え、敵を排除するには、次の手順に従ってください。
[Variables (変数)] リストで、「Eliminated」という名前の新しい変数を作成し、その型を [Boolean (ブーリアン)] に変更します。 敵を倒し、ゲームから排除する必要がある場合、こちらを使用してください。
プレイヤーへのダメージを 1 回だけ与えられるようにするには、Branch ノードの True ピンからドラッグし、Do Once ノードを作成します。
Do Once ノードの Completed ピンからワイヤーを引き出して、Apply Damage ノードを作成します。 Damaged Actor ピンをドラッグし、PlayerRef 変数への参照をつなげます。 これはダメージを受けるアクタです。
Base Damage ピンを右クリックして、[Promote to Variable (変数へ昇格)] を選択します。
[Variables (変数)] リストで Base Damage の目のアイコンをクリックして編集可能にし、[Category (カテゴリ)] を [Setup (設定)] に変更します。 ブループリントをコンパイルし デフォルト値を
「25」に設定します。Eliminated 変数を変数リストからイベント グラフにドラッグし、Set (設定) を選択します。 ノードで、チェックボックスをクリックして [Eliminated (撃破)] を true に設定します。
Apply Damage ノードの Exec ピンを Set Eliminated ノードに接続します。
Set Eliminated ノードの Exec ピンをドラッグして、Delay ノードを作成します。 Duration を
「2.0」に設定します。Delay ノードの Exec ピンをドラッグして、Destroy Actor ノードを作成します。 Target プロパティは、デフォルトでは self に設定されています。
敵がプレイヤーに衝突すると、プレイヤーにダメージを適用し、2 秒間のディレイの後、敵をキルします。
敵はプレイヤーに向かって走って、プレイヤーと衝突するとダメージを与えて、自爆できます。 ただし、プレイヤーと敵の間の距離や障害物は考慮されません。 そのため、距離や視線に関係なく、敵は常にプレイヤーを追跡します。
BP_Enemy の完成した On Component Hit ロジックは次のようになります。
以下のブループリント スニペットを BP_Enemy イベント グラフにコピーするには、変数名がサンプル プロジェクトのものと一致していることを確認してください。
距離と障害物ロジックを追加する
次に、敵がプレイヤーに十分近づいた場合にのみ検出できるように、最大検出距離を追加します。 その後、壁を通してプレイヤーが見えないようにするため、敵の視線の制限を実装します。
まず、敵とプレイヤーの間をライン トレースする新しい関数をブループリント ライブラリに作成します。
ライン トレースを使用して視線と距離を計算する
ライン トレース (またはレイキャスト) は ゲーム開発においてよく使用される手法です。 ライン トレースは、ラインが何にヒットするかを確認するために、ワールド内のポイント (ソース アクタなど) から非表示のラインを描画します。 多くの場合、ランタイム時にオブジェクトやサーフェスを検出し、トレースの結果に応じてロジックをトリガーするために使用されます。
このチュートリアルでは、プレイヤー キャラクターが敵の視界に入ったときを検出するために敵キャラクターからのライン トレースをキャストします。
ライン トレースの詳細については、「レイキャストによるトレース」ドキュメントを参照してください。
ライン トレースを使用してプレイヤーを検出する関数を設定するには、次の手順を実行します。
コンテンツ ブラウザで、「Core」フォルダに移動して、
BPL_FPGameブループリント ライブラリを開きます。「
fnBPLFindPlayer」という名前の新しい関数を追加する新しい関数の詳細パネルの[Inputs (入力)] セクションで、[Add (+) (追加 (+))] をクリックして次の入力タイプを追加します。
プレイヤー参照 (ポーンオブジェクト参照)
開始地点 (Vector)
最大検出距離 (Float)
デバッグ (Boolean)
これらの入力を追加すると、fnBPLFindPlayer 関数エントリ ノードに、各変数に対応するピンがあることがわかります。
関数の詳細パネルの[Outputs (出力)] セクションで、[Add (+) (追加 (+))] をクリックして「Found」という名前のブール型の出力値を作成します。
Found 出力を追加すると、新しい Return ノードが Found ピンと共にグラフに表示されます。
[My Blueprint (マイ ブループリント)] パネルの [Local Variables (ローカル変数)] セクションで、[Add (+) (追加 (+))] ボタンをクリックして、「PlayerFound」という名前のブール型のローカル変数を作成します。 デフォルト値が false であることを確認してください。
プレイヤー参照は関数を適切に実行するために重要であるため、エラーを回避するため、関数の開始時に有効なプレイヤー参照があるかどうかをチェックしてください。
有効な入力を確認するには、次の手順を実行してください。
Alt キーを押しながらワイヤーまたは実行ピンをクリックして、エントリ ノードと Return ノード間のワイヤーを削除します。
Function Entry ノードの後に、Is Valid ノードを作成して接続します。
ノード アクション リストの下部付近に疑問符 (?) アイコンで表される Is Valid ノードを作成してください。
エントリ ノードの Player Reference ピンを Is Valid ノードの Input Object ピンに接続します。
Is Not Valid exec ピンを Return ノードに接続します。
Found 戻り値では、PlayerFound 変数への参照を接続します。これは関数を終了し、PlayerFound=False を敵のイベント グラフに返します。
プレイヤーが有効な場合、機能はライン トレース オブジェクトを実行し、PlayerFound を返します。
ライン トレースを設定するには、以下の手順を実行します。
Is Valid exec ピンから、Sequence ノードを追加してロジックを整理します。
Sequence ノードの Then 0 ピンからドラッグし、Line Trace By Channel ノードを追加します。
Line Trace By Channel は、特定のコリジョン チャンネル上のオブジェクトを検出します。 ブループリントのコリジョン チャンネル設定を表示するには、ブループリントのコリジョン コンポーネントを選択し、[Collision (コリジョン)] > [Collision Presets (コリジョン プリセット)] プロパティを詳細パネルで確認してください。 [Trace Responses (トレース応答)] セクションには、[Visibility (可視性)] および [Camera (カメラ)] チャンネルがあります。
関数エントリ ノードから Start Location ピンをドラッグし、Line Trace By Channel ノードの Start ピンに接続します。 敵キャラクターの位置をライン トレースの開始点として設定します。
グラフを整理するため、Get Player Reference ノードを作成します。 ノードの右上隅にある「f」アイコンは、それが関数入力であることを示します。 他の変数と同じように、これらの入力にも参照を追加できます。
Player Reference ピンをグラフ内の空いている場所にドラッグしてください。 これにより、ノード アクション リストが開きます。 リスクで、Get Actor Location ノードを検索して作成します。
その [Return Value (戻り値)] を Line Trace ノードの End ピンに接続します。 これにより、ライン トレースがそのプレイヤーの場所で終了します。
Line Trace By Channel ノードで、ドロップダウン メニューを使用して [Trace Channel (トレース チャンネル)] プロパティを [Camera (カメラ)] に設定します。
これでライン トレースの開始位置と終了位置が設定できたので、トレースが何かにヒットした場合にどうなるかを定義してください。
ライン トレースがプレイヤーにヒットしたかどうかをチェックするには、次の手順に従ってください。
ライン トレースの Out Hit ピンからドラッグして、Break Hit Result ノードを追加します。 ライン トレースがオブジェクトにヒットすると、多くの情報が収集されます。 いくつかの特定の値のみを使用する必要があるため、Break Hit Result ノードを使用して、データを返されたデータの個々のコンポーネントに分割する必要があります。
Break Hit Result ノードで、下部の矢印をクリックすると、その他のオプションが表示されます。
プレイヤーが敵との一定の距離内にいて視界上にいるかどうかを把握したいため、Hit Actor ピンを使用してプレイヤーかどうかを確認し、Trace Start と Trace End を使用して距離を測定しますヒットオブジェクトにバインドしました。
Hit Actor ピンからドラッグして Equal 演算子ノードを追加します。 下の入力では、Player Reference 関数の入力への参照を接続します。
関数の入力値を参照するには、他の変数と同様に Get ノードを追加できます。
Distance (Vector) ノードを作成します。 V1 を Trace Start に接続し、V2 を Trace End に接続してください。
ベクターは、3D 空間でのオブジェクトまたはポイントの位置を表す X、Y、および Z の値のセットです。 Distance ノードは、これら 2 つのポイントの間の距離を計算します。その結果が float 値になります。
Distance ノードの Return 値からドラッグし、Less (<) ノードを追加します。 下の入力では、Max Detection Distance 関数の入力への参照を接続します。
AND (Boolean) ノードを作成します。
Equals (==) および Less (<) ノードのブール型出力ピンの両方を AND ノードの入力ピンに接続します。
このロジックでは、ライン トレースがライン トレースをヒットすると、Player Reference と等しい場合、トレースの開始 (敵) と終了 (ヒット オブジェクト) の間の距離が Max Detection Distance よりも小さい場合は、AND ノードは True を返します。
トレース結果を使用して PlayerFound の値を設定したり返したりするには、以下の手順に従ってください。
AND ノードの出力からドラッグし、Branch ノードを追加します。
Line Trace By Channel の後に実行されるように実行ピンを接続します。
Branch ノードの True 実行ピンから、Set 変数ノードを作成して、ローカルの PlayerFound 変数を true に設定します。
Branch ノードの False ピンから、Set PlayerFound 変数を作成します。 値は false のままにします。
ライン トレース ロジックが完了したので、Sequence ノードに戻り、その Then 1 ピンを Return ノードに接続して、関数を終了し、敵のブループリントに PlayerFound 結果を戻します。
ライン トレース デバッグ オプションを追加
Line Trace のデバッグ用ビジュアルは、レベル エディタから簡単にオンとオフを切り替えることができるようにする必要があります。 ただし、Line Trace ノードでは、[Draw Debug Type (描画デバッグ タイプ)] リストから 1 つのオプションのみを選択できます。 Select ノードを使用して、レベル エディタでデバッグ タイプを編集可能にすることができます。
ライン トレースにカスタマイズ可能なデバッグ オプションを設定するには、次の手順を実行します。
Line Trace By Channel ノードの Draw Debug Type ピンからワイヤーをドラッグして、Select ノードを作成します。
Select ノードの Index ピンを関数のデバッグ入力への参照に接続します。
Select ノードのインデックスはワイルドカードであるため、ブーリアン型の Debug の値を接続すると、オプションは False と True のオプションに変わります。
False オプションを [None (なし)] に設定します。 For Duration オプションを True に設定します。
Line Trace By Channel ノードの下部にある矢印ボタンをクリックすると、その他のオプションが表示されます。 [Draw Time (描画時間)] を
0.1秒に変更しますブループリント関数ライブラリを保存してコンパイルします。
このロジックは Debug 変数を使用して、ライン トレースのデバッグ描画がアクティブかどうかを判断します。
Debug 変数が false の場合[Draw Debug Type (描画デバッグ タイプ)] は [None (なし)] に設定され、デバッグ描画はレンダリングされません。
[Debug (デバッグ)] が true に設定されている場合、Select ノードは [Draw Debug Type (描画デバッグ タイプ)] を [For Duration (持続時間)] に変更します。これにより、ランタイム時に設定された持続時間だけライン トレースがレンダリングされます。
完成した fnBPLFindPlayer 関数は次のようになります。
このブループリント スニペットをプロジェクトにコピーする場合、関数入力ノードの Exec および Player Reference ピンを Is Valid ノードの Exec および Input Object ピンに接続する必要があります。 スニペットを正しくコピーするため、関数入力の名前がサンプル プロジェクトのものと一致していることを確認してください。
プレイヤーへの移動ロジックをアップデートする
距離と視線を考慮しながらプレイヤーを検索する機能を呼び出せるようになったので、発見時、またはライン トレースがプレイヤーを検出できた場合のみ、プレイヤーを探して追跡するロジックを敵に追加できました。
敵がプレイヤーを見つけた後にプレイヤーを追跡するようにするには、次の手順に従います。
BP_Enemyブループリントに戻ります。 イベント グラフで、指定された Event Tick ノードを見つけてください。Event Tick ノードの実行ピンをドラッグし、Branch ノードを作成します。
ゲームのプレイ中に各フレームで On ティック イベントが実行されます。 敵が常にプレイヤーの位置をチェックし、追跡を開始するかどうかを判断するようにするために使用します。
Branch ノードの条件ピンをドラッグし、ブール値の逆数を返す NOT Boolean ノードを作成します。
この場合、Eliminated 変数を反転する必要があるため、NOT ノードの入力ピンをドラッグし、「Get Eliminated」を検索します。
Branch ノードの True ピンで続行する前に、敵が撃破されていないかチェックされます。
Branch ノードの True ピンをドラッグし、FnBPLFindPlayer ノードを作成します。 このノードは、ワールド内のプレイヤーを見つけるライン トレースを実行し、敵とプレイヤーの現在の距離をチェックします。
Fn BPLFind Player ノードで、そのピンを使用して次のように接続します。
プレイヤー参照:PlayerRef 変数への参照を接続します。
開始位置ターゲット:[Target (ターゲット)] プロパティを self に設定した Get Actor Location ノードを作成します。 これにより、ライン トレースの開始位置がワールド内の敵の位置に割り当てられます。
最大検出距離:ピンを右クリックして、[Promote to Variable (変数へ昇格)] を選択します。 目のアイコンをクリックして編集可能にしカテゴリを [Setup (設定)] に変更します。 コンパイルし、[Default Value (デフォルト値)] を
20000(200 メートル) に設定します。 この値が小さいほど、プレイヤーは敵にプレイヤーを検知させるために近くにいる必要があります。デバッグ:[Promote to Variable (変数への昇格)] を選択し、「
DebugDetection」という名前を付けます。 また、この変数を編集可能に設定し、[Setup (設定)] カテゴリに表示します。
プレイヤーがライン トレースによって見つかった場合は、敵の最大移動速度を適切な速度に設定し、敵をプレイヤーに向かって移動させます。 有効でない場合は、速度を 0 に設定し、敵がプレイヤーに向かって移動できないようにします。
プレイヤーが見つかった場合に敵が動き、見つからなかった場合は停止するようにするには、次の手順に従ってください。
FnBPLFindPlayer ノードで、Found ピンを右クリックし、[Promote to Variable (変数へ昇格)] を選択します。 これで、その新しい変数に対する Set ノードが自動的に接続されます。 これで、見つかった結果をグラフ内の別の場所で使用することができます。
Set ノードの後に、Branch ノードを接続します。 Branch ノードの Condition ピンを Set Found ノードの出力ピンにドラッグします。
[Components] パネルで、Character Movement (CharMoveComp) をイベント グラフにドラッグします。 そのピンをドラッグして、Set Max Walk Speed ノードを作成します。
Branch ノードの True ピンをドラッグし、Set Max Walk Speed ノードに接続します。
Set ノードの Max Walk Speed ピンに、Max Speed 変数への参照を接続してください。
Set ノードの後に、MoveToPlayer ノードを接続して、このイベントを呼び出し、プレイヤーを見つけた場合のみに敵が動くようにします。
Set Max Walk Speed ノードと Character Movement ノードを複製します。 Branch ノードの False ピンを新しい Set ノードに接続します。
2 つ目の Set Max Walk Speed ノードで、歩行速度値が「0」であることを確認してください。 これにより、敵は、その AI MoveTo タスクをキャンセルせずに移動を停止し、タスクを再度実行する必要があります。
これで、敵がフレームごとにプレイヤーを探すようになったので、Event BeginPlay ロジックの最後に追加した Move to Player ノードを削除します。 このノードは、完成途中の敵をテストするのに役立ちましたが、必要はありません。
MoveToPlayer のイベント ロジックに移動します。 次に、プレイヤーが見つかった場合にのみ、敵にこのイベントを実行させるようにします。
MoveToPlayer ノードをドラッグして、Branch ノードを作成します。
Branch の条件として Found 変数への参照を追加します。
これで、プレイヤーが敵との指定された距離内にいて、2 つの間に障害物がない場合、敵の移動速度は MaxSpeed 変数に設定され、MoveToPlayer ロジックが実行されます。 これらの条件のいずれかが満たされていない場合、敵の移動速度は 0 に設定され、敵がプレイヤーに向かって移動するのをブロックします。
BP_Enemy の最終的な変数リストは次のようになります。
以下のブループリント スニペットを BP_Enemy イベント グラフにコピーするには、変数名がサンプル プロジェクトのものと一致していることを確認してください。
BP_Enemy の最終的な Event BeginPlay ロジックは次のようになります。
BP_Enemy の最終的な MoveToPlayer ロジックは次のようになります。
BP_Enemy の最終的な Event Tick ロジックは次のようになります。
敵がダメージを受けることを許可
このブループリントを終了する前に、敵もダメージを受けることができるようにする必要があります。 このチュートリアル シリーズの終了後もゲームを続ける場合は、敵にトラップでダメージを与えたり、敵にダメージを与えて倒すことができる装備可能なアイテムをプレイヤーに提供したりしてもよいでしょう。
敵にダメージを与えるには、次の手順を実行してください。
イベント グラフ内の任意の場所を右クリックして Event AnyDamage ノードを作成します。
Event AnyDamage の実行ピンをドラッグし、Set CurrentHP ノードを作成してください。
CurrentHP によるダメージを減算するには、Current HP プロパティのピンをドラッグして、Subtract ノードを作成します。
ノード次に、Subtract ノードの上のピンをドラッグして Get Current HP ノードを作成します。
Subtract ノードの下のピンを Event AnyDamage ノードの Damage プロパティに接続します。
このアクタにダメージが与えられると、これは CurrentHP 変数の値を受け取り、その値からダメージを減算してから、CurrentHP の値を新しい値に設定します。
次に、CurrentHP が 0 以下の値であるかどうかを確認します。CurrentHP が 0 以下の値の場合、敵が撃破されます。
敵の HP が 0 になったときにその敵を排除するには、次の手順を実行します。
Set ノードのピンをドラッグし、新しい Branch ノードを作成します。
Branch ノードの Condition ピンをドラッグし、Less Equal (<=) ノードを作成します。
Set Current HP ノードの出力ピンを Less Equal ノードの上部入力ピンに接続してください。 下側のピンが「0」に設定されていることを確認してください。
Branch ノードの True ピンからドラッグし、Do Once ノードを作成します。
その Completed ピンをドラッグして、Set Eliminated ノードを作成します。 Set ノードで、Eliminated プロパティを true に切り替えます。
Set ノードの後に、Duration が
2に設定されている Delay ノードを接続します。Delay ノードの Completed ピンをドラッグして、Target プロパティを「self」に設定した Destroy Actor ノードを作成します。
ブループリントを保存してコンパイルします。
BP_Enemy の完成した Event AnyDamage ロジックは次のようになります。
完成した敵キャラクターをテストする
この時点でゲームをプレイすると、敵とプレイヤーの距離によっては敵は動いていないことがあります。 敵に近づくと、敵がプレイヤーの追跡を開始します。
障害物を使ってみましょう。 プレイ モードを終了し、メイン ツールバーの [Create (作成)] ボタンを押して [Shapes (形状)] > [Cube (キューブ)] を選択することで、NavMesh ゾーンの中央にブロックアウト キューブまたはウォールを追加します。 この障害物は NavMesh にカットされます。
プレイヤーがこの障害物の背後で開始した場合、ライントレースはキューブで遮られるため敵はプレイヤーを追跡できず、結果としてプレイヤーを見つけることができません。 プレイヤーがキューブの周りを歩き、敵がプレイヤーを直視した場合、敵はプレイヤーの追跡を開始します。 敵が AI MoveTo アクションを開始すると、障害物の背後に隠れていても敵の追跡は停止されません。
プロジェクト内の敵の位置を配置する
このサンプル レベルでは、ホールウェイ 3 とルーム 3 に複数の敵を配置しました。 最初の敵はホールウェイ 3 に 1 つ配置されました。これは、プレイヤーが敵動作とその能力について学び、精通するためのシンプルな最初の遭遇を与えることが目的です。 廊下で 1 体の敵に遭遇した後、ルーム 3 に 2 つの敵キャラクターを配置し、プレイヤーにさらなる挑戦を用意しました。
敵の数とタイプを変えて、プロジェクト全体に異なるレベルの難易度を設定することができます。 プレイヤーを新しい敵や課題に徐々に導いていくことで、バランスの取れた難易度カーブを作成し、プレイヤーが時間の経過とともにこのゲームに慣れることができます。 困難な敵との遭遇を作成することで、プレイヤーにナビゲーションの方法や敵を倒す方法を学んだ後に、プレイヤーにやりがいのある課題を提供することができます。
次の内容
次のモジュールでは、プレイヤーの移動セットにダッシュ メカニックを追加する方法を学習します。 これは、プレイヤーがレベル内のよく知っている場所を移動するのに役立ち、また、プロジェクトに追加した敵を避けるためのツールをプレイヤーに提供できます。