
敵、Part 2:動き回る監視員
Tutorial
Beginner
+0XP
40 mins
Unity Technologies

John Lemon が避けなければならない敵を 1 つ作成しましたが、それはそれほど難しくなかったように思えます。そろそろプレイヤーのチャレンジ難易度を上げるような別の敵を作成する時が来ました。
このチュートリアルでは、以下の作業を行います。
- 動き回る敵、ゴーストを作成する
- ゴーストがお化け屋敷をパトロールできるようにカスタムスクリプトを書く
- ゲームに敵を投入する
チュートリアルを終えると、ゲームは敵だらけになり、ほぼ完成した状態になります。
1. Ghost プレハブのセットアップ
4. 前回のチュートリアルでは、お化け屋敷用にガーゴイルの敵を作成しました。次は、動的な(動き回る)敵を作成することで、レベルの難易度を高めます。今回は、JohnLemon を探して屋敷の廊下をうろつくゴーストを作成します。
ゴーストのモデルを使用するための最初のステップは、プレハブを作成することです。今のうちに、このプロセスをよく理解しておいた方がいいです。
1. Project ウィンドウで、 Assets > Models > Characters の順にフォルダを開き、 Ghost(ゴースト)アセットを見つけます。
2. Project ウィンドウから Hierarchy ウィンドウに Ghost モデルをドラッグして、モデルのインスタンスを作成します。
3. Hierarchy ウィンドウの Ghost ゲームオブジェクトを Project ウィンドウの Assets > Prefabs フォルダの順に選択し、ドラッグします。Create Prefab ダイアログボックスが表示されたら、 Original Prefab を選択します。
4.編集のためにプレハブを開きます。
2. ゴーストにアニメーションを加える
次のステップでは新しい敵にアニメーションを加えます。また、ゴーストは 1 つのアニメーションをループで再生するため、シンプルなアニメーションコントローラーもあります。
ゴーストにアニメーションを加えるには、以下の手順に従ってください。
1. Project ウィンドウで、 Assets > Animation > Animators フォルダの順に移動し、右クリックします。
2. コンテキストメニューで、 Create > Animator Controller の順に選択します。新しいアニメーションコントローラーの名前を「Ghost」とします。
3. Ghost をダブルクリックして、Animator ウィンドウを開きます。
4. Project ウィンドウで、 Assets > Animation > Animations の順に進みます。
5. Ghost@Walk Model アセットを展開します。
6. Project ウィンドウから Walk アニメーションを Animator ウィンドウにドラッグします。
ゴーストのシンプルなアニメーションコントローラーは完成しましたが、まだ Animator コンポーネントに割り当てる必要があります。
7. Project ウィンドウで、 Assets > Animation > Animators フォルダの順に進みます。
8. Hierarchy ウィンドウで、 Ghost ゲームオブジェクトを選択します。
9. Project ウィンドウから Ghost の Animator Controller を Inspector で Ghost の Animator コンポーネントの Controller プロパティにドラッグします。
10. シーンの保存
3. ゴーストにコライダーを追加する
JohnLemon やガーゴイルのように(おそらく、少し反感を買うかもしれませんが)、ゴーストはシーン内で物理的な存在感を必要とします。つまり、コライダーが必要になるということです。
コライダーを追加するには以下の手順に従ってください。
1. Unity エディターが Prefab モードのままであることを確認してください。そうでない場合は、Gargoyle プレハブを作成したときに習得したショートカットを使うことができます。
2. Inspector で、Ghost ゲームオブジェクトに Capsule Collider コンポーネント を追加します。
3. コライダーが Ghost モデルの形状により良くフィットするように設定を調整しましょう。
- Capsule Collider の Center プロパティを(0, 0.6, 0)に変更する
- Radius プロパティを 0.25 に変更する
- Height プロパティを 1.2 に変更する
これでコライダーがよくフィットするようになりました!
4. Ghost ゲームオブジェクトに Rigidbody コンポーネントを追加する
ゴーストは動いているのでリジッドボディも必要になります。この設定には注意が必要です。JohnLemon と衝突しても、ゴーストの中でいかなる動きも生じることがないようにしましょう。
位置と回転のすべての制約を有効にすることで動くことを避けることができますが、より簡単なアプローチとしては、リジッドボディを kinematic に設定することです。
Inspector で、Ridigbody コンポーネントを見つけ、 Is Kinematic チェックボックスを有効にします。
キネマティック リジッドボディは、衝突などの外力の影響を受けませんが、他のゲームオブジェクトと衝突する可能性があります。ゲーム 『Breakout』のパドルは、キネマティック・リジッドボディの完璧な例(ボールはパドルから跳ね返るが、パドルは跳ね返りの影響を受けない)です。
5. ゴーストを監視員にする
ゴーストのプレハブには基本的な機能がすべて揃っていますが、現在動いたり JohnLemon を見つけたりすることはありません。これを制御する Gargoyle プレハブ用の PointOfView ゲームオブジェクトはすでに作成しています。すべての作業を繰り返すのではなく、それのプレハブを作成しましょう!
ゴーストを監視員にするには以下の手順に従ってください。
1. 最初に、変更した内容をゴーストプレハブに保存します。
2. Project ウィンドウで、 Assets > Prefabs フォルダの順に開き、 Gargoyle プレハブを選択します。
3. Inspector ウィンドウで、 Open Prefab ボタンをクリックします。
4. Hierarchy で、Gargoyle の子として作成した PointOfView ゲームオブジェクトを見つけます。
このゲームオブジェクトをプレハブに変換して、Gargoyle プレハブと Ghost プレハブの両方で参照できるようにします。
5. Hierarchy ウインドウから PointOfView ゲームオブジェクトを Project ウインドウの Assets > Prefabs の順に選択しフォルダにドラッグします。
6. Hierarchy の PointOfView ゲームオブジェクトがグレーではなくブルーの立方体で表されるようになり、名前もグレーではなくブルーになっていることがわかるはずです。これは、Prefab のインスタンスになったからです!
7. Gargoyle プレハブの保存
8. Project ウィンドウで、 Assets > Prefabs フォルダの順に進み、 Gargoyle プレハブを選択します。Open Prefab ボタンをクリックします。
9. Assets > Prefabs フォルダの順に選択し PointOfView プレハブを Hierarchy ウィンドウの Ghost ゲームオブジェクトにドラッグします。
これで、ゴーストにも PointOfView が追加され、その機能をすべて使えるようになりました!この敵に対して PointOfView が正しく動作するように 2, 3 調整する必要があります。ガーゴイルはゴーストよりも背が高く下を向いていますが、ゴーストはまっすぐ前を向く必要があります。
10. Hierarchy ウィンドウで、 PointOfView ゲームオブジェクトを選択します。
11. Inspector で、その Transform コンポーネントを見つけます。
- Position プ ロパティを(0, 0.75, 0.4)に変更します。
- Rotation プ ロパティを(0, 0, 0)に変更します。
これでゴーストは監視員として設定されました。また、必要に応じて、PointOfView プレハブを変更しゲーム内の両方の敵を更新することもできます。
6. NavMesh Agent コンポーネントの設定
さあ、ゲーム環境の中を動き回れるようにゴーストをセットアップする準備ができました。
これを行うには、以下の 2 つのコンポーネントを使用します。
- Nav Mesh Agent:環境チュートリアルで作成したナビメッシュの周りのパスをゴーストが見つけられるようにする
- スクリプト:ゴーストが行くべき場所を Nav Mesh Agent に伝える
まずは Nav Mesh Agent の作成から始めましょう。
1. Inspector で、 Nav Mesh Agent コンポーネントを Ghost ゲームオブジェクトに追加します。
ほとんどの場合、このコンポーネントのデフォルト設定を使用することができますが、調整が必要なものがいくつかあります。
2. Scene ビューでは、ゴーストの周りに Nav Mesh Agent がシリンダー表示されているはずです。
これはちょっと大きいですね。Inspector で、Nav Mesh Agent コンポーネントの Radius プロパティを 0.25 に変更します。
エージェントの高さよりもゴーストよりはかなり高いですが、天井がない環境なのでこれは関係ないでしょう。
3. Nav Mesh Agent コンポーネントの Speed プロパティを 1.5 に変更します。1 秒あたり 3.5 メートルというデフォルトの速度は、ゴーストにしてはかなり速く、ゲームが少し難しくなります。
4. Nav Mesh Agent コンポーネントの Stopping Distance プロパティを 0.2 に変更します。ゴーストが取得するウェイポイントにどれだけ近いかについてあまり正確にする必要はありません。そのため、ナビメッシュエージェントは目的地から到達できる距離を増やしても、エージェント自体が到着したと見なすことができます。
5. 変更内容の保存
Nav Mesh Agent の設定は完了しましたが、それだけでは何もしません。目的地を設定しておく必要があります。そのためにはスクリプトを書く必要があります。
7. 新しい WaypointPatrol スクリプトを作成する
ゲーム内のゴーストは、ウェイポイントの集まりをループしてパトロールすることによって移動するので、このスクリプトをWaypointPatrol と呼ぶことは理にかなっています。変更内容を保存することを忘れないでください。
新しいスクリプトを作成するには:
Project ウィンドウで、 Assets > Scripts の順に進みます。
1. Scripts フォルダーを右クリックし、 Create > C# Script を選択します。新しいスクリプトに「WaypointPatrol」という名前を付けます。
2. Hierarchy で、Ghost ゲームオブジェクトを選択します。
3. 新しく作成した WaypointPatrol スクリプトを Project ウィンドウから Inspector ウィンドウにドラッグして、コンポーネントとして Ghost に追加します。
4. WaypointPatrol スクリプトをダブルクリックすると、編集用のスクリプトが開きます。
8. ナビメッシュエージェントの目的地を設定する
スクリプトの編集を始める前に、何をする必要があるのかを簡単に考えてみましょう。シーンが最初にロードされたときと、ゴーストが目的地に到達したときの両方で、ナビメッシュエージェントの目的地を設定する必要があります。いつ目的地に到達したかを知るためには、すべてのフレームをチェックする必要があります。
新しいスクリプトの編集を始めましょう。
1. このスクリプトでは Start メソッドと Update メソッドの両方が必要になるため、今までのようにそれらを削除しても意味がありません。代わりに、Start メソッドと Update メソッドの上にあるコメントを削除してください。
スクリプトは以下のようになります。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WaypointPatrol : MonoBehaviour
{
void Start ()
{
}
void Update ()
{
}
}2. Nav Mesh Agent に目的地を伝える必要があるので、それを参照する必要があります。Nav Mesh Agent でスクリプトを実行するには、その名前空間を含める必要があります。
他の using ディレクティブを使用しているスクリプトの先頭に、以下のコードを追加します。
using UnityEngine.AI;AI 名前空間を含めると、NavMeshAgent クラスにアクセスできるようになります。
3. Start メソッドの上に、以下を追加します。
public NavMeshAgent navMeshAgent;このコンポーネントへの public 参照を使用すると、Inspector ウィンドウで Nav Mesh Agent 参照を割り当てることができます。
4. 次に、ゴーストがパトロールするウェイポイントを設定する必要があります。ナビメッシュエージェントの目的地は Vector3(ワールドスペース内の位置)です。ただし、ウェイポイントを Vector3s にした場合、すべての位置を手動で設定し、使用する数値が正確であると期待するしかありません。
代わりに、空のゲームオブジェクトのコレクションを用意し、それらの位置をウェイポイントとして使用することは理にかなっています。これらのゲームオブジェクトは、シーンの周りをより簡単に移動することができ、あなたが行いたい変更をもっとシンプルに行うことができます。しかし、ゲームオブジェクトのコレクションへの参照を持つのではなく、それらの Transform コンポーネントへの参照を持つことができます。単に複数の public Transform 変数を持っていて、Inspector ウィンドウでそれぞれ個別に設定することもできますが、それでは、各ゴーストが持つことができるウェイポイントの数に柔軟性がありません。
その代わりに、配列と呼ばれるものを使うことができます。配列は、一緒に存在する変数の基本的なコレクションです。これらは角括弧を使用して定義されています。
navMeshAgent 変数宣言のすぐ下に以下の行を追加します
public Transform[] waypoints;このコードの行では、 waypoints という public 変数を宣言していますが、これは Transform の配列です。
5. 次に、Start メソッドに行を追加して、Nav Mesh Agent の最初の目的地を設定します。
navMeshAgent.SetDestination(waypoints[0].position);9. 配列の仕組み
配列がどのように機能するかについてもう少し理解するために、これを詳しく探ってみましょう。
コード行が Nav Mesh Agent コンポーネントの SetDestination メソッドを呼び出しています。これは Vector3 をパラメーターとして取得するため、配列内の最初の waypoint 本体の値、Transform の position プロパティを使用しています。
配列を構成する個々のものを要素と呼びます。配列内の個々の要素には、角括弧内のインデックスを使用してアクセスします。インデックスは、目的の要素に到達するために配列の先頭からスキップする必要がある要素の数と考えてください。最初の要素にアクセスするために要素をスキップする必要がないため、そのインデックスは 0 です。
10. 新たな目的地を追加する
スクリプトに追加していきましょう。
1. ゴーストは、目的地として設定した最後のウェイポイントに到達したら、次のウェイポイントに移動する必要があります。次のウェイポイントを追跡する最も簡単な方法は、ウェイポイント配列の現在のインデックスを保存することです。
waypoints の配列宣言の下に、以下のコードを追加します。
int m_CurrentWaypointIndex;2. 次に、このインデックスを使えるように Update メソッドに移りましょう。
Update メソッドでは、チェックを実行する必要があります。ナビメッシュエージェントが目的地に到着したかどうかを確認します。これを簡単に確認する方法は、目的地までの残りの距離が、先ほど Inspector ウィンドウで設定した停止距離以下になっているかどうかを確認することです。
Update メソッドに以下の if 文を追加します。
if(navMeshAgent.remainingDistance < navMeshAgent.stoppingDistance)
{
}
3. 次に、現在のインデックスを更新し、それを使用してナビメッシュエージェントの目的地を設定する必要があります。これを行うには、パーセント文字「%」で表される剰余演算子(remainder operator)と呼ばれる新しい演算子を使用します。
if 文の中に以下のコードを追加します。
m_CurrentWaypointIndex = (m_CurrentWaypointIndex + 1) % waypoints.Length;剰余演算子は、左側にある値は何でも取得し、右側にある値で除算して余りを返します。例えば、3 % 4 は 3 を返します(4 は 3 を残して 3 回ゼロになるので)。5 % 4 は 1 を返します(4 は 1 を残して一度 5 に入るので)。
コードには「現在のインデックスに 1 つ追加しますが、インデックスがウェイポイント配列の要素数と同じになる場合は 0 に設定します。」と書いてあります。このような状況では、任意の数を1で割ったときの残りが 0 になるので、この場合は 0 になります。
4. これでインデックスをインクリメントした(必要に応じてループしてゼロに戻した)ので、それを使う必要があります。インデックスのインクリメントの下に以下を追加します。
navMeshAgent.SetDestination (waypoints[m_CurrentWaypointIndex].position);これは Start メソッドで行ったことと全く同じですが、0 をインデックスとして使用する代わりに、ゴーストが現在位置のウェイポイントをインデックスとして使用しています。
5. これだけです!完成したスクリプトは以下のようになります。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class WaypointPatrol : MonoBehaviour
{
public NavMeshAgent navMeshAgent;
public Transform[] waypoints;
int m_CurrentWaypointIndex;
void Start ()
{
navMeshAgent.SetDestination (waypoints[0].position);
}
void Update ()
{
if(navMeshAgent.remainingDistance < navMeshAgent.stoppingDistance)
{
m_CurrentWaypointIndex = (m_CurrentWaypointIndex + 1) % waypoints.Length;
navMeshAgent.SetDestination (waypoints[m_CurrentWaypointIndex].position);
}
}
}
6. スクリプトを保存して Unity エディターに戻ります。
11. Nav Mesh Agent への参照を Ghost プレハブに割り当てる
Inspector ウィンドウでは、Nav Mesh Agent への参照およびwaypoints(ウェイポイント)にいくつかトランスフォームを割り当てる必要があることが確認できます。Nav Mesh Agent への参照は、プレハブのすべてのインスタンスで同じになるため、ここで割り当てることができます。しかし、ウェイポイントはゴーストごとに異なるので、プレハブの一部にすべきではありません。それだけでなく、ウェイポイントはシーンの一部になるので、ゴーストのプレハブから参照できません。
1. Hierarchy ウィンドウで、 Ghost ゲームオブジェクトを選択します。
2. Inspector ウィンドウの Nav Mesh Agent コンポーネントの名前を Waypoint Patrol スクリプトの Nav Mesh Agent フィールドにドラッグします。これにより、Nav Mesh Agent への参照が割り当てられます。
3. Ghost プレハブを保存し、シーンに戻ります。
4. Ghost の Observer スクリプトに必要な参照があることを確認してみましょう。Hierarchy で、Ghost ゲームオブジェクトを展開し、 PointOfView の子ゲームオブジェクトを選択します。
5. JohnLemon ゲームオブジェクトを Hierarchy ウィンドウから Observer スクリプトの Player フィールドにドラッグして、その Transform を割り当てます。
6. 次に、丸い選択式のボタンをクリックして GameEnding フィールドを割り当てます。シーンには GameEnding コンポーネントが 1 つしかないので、選択するオプションは 1 つだけです。
敵は、これでかなり完成に近づいています!あとはゴーストを追加してウェイポイントを割り当て、さらに動かないガーゴイルを 2, 3 追加するだけです。
12. シーンにゴーストを配置する
これでシーンに敵を追加する準備ができました!まず、4 匹の複製ゴーストを作成し、レベルに動き回る敵を配置します。
1. Hierarchy ウィンドウで、折りたたみ Ghost ゲームオブジェクトを選択します。Ghost のコピーが 4 つになるまで Ctrl + D(Windows)またはCMD + D(macOS)を押して、ゲームオブジェクトを複製します。
2. 最初のゴーストは JohnLemon が入る部屋の近くで前後に動いているはずです。Inspector で、 Ghost という名前のゴーストの position を(-5.3, 0, -3.1)に設定します。
3. 2 匹目のゴーストは長い廊下を行ったり来たりしているので、JohnLemon は横の部屋に素早く身を隠さないと通り抜けられません。Ghost (1) という名前のゴーストの position を(1.5, 0, 4)に設定します。
4. 3 匹目のゴーストは、一つのダイニングルームの中でテーブルを一周します。Ghost (2) という名前のゴーストの position を(3.2, 0, 6.5)に設定します。
5. 最後のゴーストは出口付近の寝室で動き回るので、JohnLemon が間違った方向に行くと捕まってしまいます。Ghost (3) という名前のゴーストの position を(7.4, 0, -3)に設定します。
これでゴーストを配置できました。次に、ウェイポイントを作成して配置する必要があります。
13. ゴーストのウェイポイントの作成と配置
ウェイポイントは空のゲームオブジェクトの状態である必要があります。これは、Transform コンポーネントのみを使用しており、すべてのゲームオブジェクトは Transform を持っているからです。できるだけ効率を上げるために、すべてのウェイポイントを作成して、位置を決めて割り当てます。
ウェイポイントを設定して割り当てるには、以下の手順に従ってください。
1. Hierarchy ウィンドウで、Create ボタンをクリックし、 Create Empty を選択します。
2. 新しく作成した空のゲームオブジェクトの名前を「Waypoint」に変更します。
3. Waypoint ゲームオブジェクトを 9 回複製し、合計 10 個のウェイポイント(Waypoint から Waypoint (9) まで)を作成します。
4. Hierarchy で、 Ghost ゲームオブジェクトを選択します。
5. Inspector で、 Waypoint Patrol コンポーネント が表示されるまで下にスクロールします。
6. Hierarchy ウィンドウから Waypoint ゲームオブジェクトを Waypoints フ ィールドの名前の上にドラッグして配列に追加します。
7. Waypoint (1) ゲームオブジェクトを Waypoints フィールドの名前の上にドラッグして配列に追加します。
8. 最初のゴーストの配列には 2 つのウェイポイントがありますが、それらを配置する必要があります。ゴーストはスタートする部屋を通って前後に移動します。
- Inspector で、 Waypoint の position を(-5.3、0、6.7)に設定します。
- Waypoint (1) の position を(-5.5, 0, -4.5)に設定します。
9. 2 匹目のゴーストは、側面にお部屋がある廊下を上下に移動していきます。Ghost (1) ゲームオブジェクトを選択し、その Waypoints 配列に Waypoint (2) と Waypoint (3) を割り当てます。
- Waypoint (2) の position を(1.2, 0, 7.7)に設定します。
- Waypoint (3) の position を(0.9, 0, -3.5)に設定します。
10. 3 匹目のゴーストはダイニングルームのテーブルを周回しているため、もっとウェイポイントが必要になりそうです。
- Ghost (2) ゲームオブジェクトを選択し、その Waypoints 配列に Waypoint (4)、Waypoint (5)、Waypoint (6)、Waypoint (7) を割り当てます。
- Waypoint (4) の position を(3.2, 0, 5.6)に設定します。
- Waypoint (5) の position を(3.2, 0, 12.3)に設定します。
- Waypoint (6) の position を(6.5, 0, 12.3)に設定します。
- Waypoint (7) の position を(6.5, 0, 5.6)に設定します。
11. 最後のゴーストは右下の寝室にいます。Ghost (3) ゲームオブジェクトを選択し、その Waypoints 配列に Waypoint (8) と Waypoint (9) を割り当てます。
- Waypoint (8) の position を(3.2, 0, -5)に設定します。
- Waypoint (9) の position を(7.4, 0, -2)に設定します。
以上です。ゴーストが完成しました!
14. シーンにガーゴイルを配置する
次に、3 頭のガーゴイルをレベルに配置します。
1. Gargoyle ゲームオブジェクトを 2 回複製して、合計 3 頭のガーゴイルを作成します。
2. 最初のガーゴイルを配置しましたね。2 頭目は長い通路の廊下に配置する必要があるので、JohnLemon はあまり下に行けません。
- Gargoyle (1) の position を(-2.6, 0, -8.5)に設定します。
- Gargoyle (1) の rotation を(0, 30, 0)に設定します。
3. 3 頭目のガーゴイルはダイニングルームの横の廊下の隅に配置するので、JohnLemon は道を間違えると捕まってしまいます。最初のガーゴイルと同じコーナーに配置するので、回転を変更する必要はありませんが、位置を調整する必要があります。
- Gargoyle (2) の position を(-4.8, 0, 10.6)に設定します。
これで、JohnLemon の脱出をより困難にするために、レベルにさまざまな敵が配置されました。
15. ヒエラルキーを整理する
敵とそのウェイポイントを完全に完了する前に、やるべきことが最後にもう 1 つあります。それを整理してしまいましょう。現在、Hierarchy ウィンドウが少し乱雑に見えています。
最良の解決策は、敵やウェイポイントの親として機能する空のゲームオブジェクトを作成することです。これにより、必要に応じてそれらを展開したり、折りたたんだりすることができ、Hierarchy ウィンドウをきれいに整頓した状態に保つことができます。
Hierarchy を整理するには、以下の手順に従ってください。
1. Hierarchy ウィンドウに空のゲームオブジェクトを作成します。その名前を「Enemies」に変更します。
2. Inspector で、Enemies の position を(0, 0, 0)に設定します。これは、すべての Ghost および Gargoyle ゲームオブジェクトの親として動作します。
3. Ctrl キー(Windows)または CMD キー(macOS)を押しながら、Hierarchy ウィンドウで Ghosts と Gargoyles それぞれクリックします。すべて選択されたら、それらを Enemies(敵)ゲームオブジェクトにドラッグして親にします。
これで好きな時に敵を展開したり折りたたむことができるようになりました。次に、ウェイポイントについても同じことをする必要があります。
4. Hierarchy ウィンドウで、空のゲームオブジェクトを作成します。その名前を「Waypoints」に変更します。
5. Inspector で、Waypoints の position を(0, 0, 0)に設定します。これは、すべての Ghost および Gargoyle ゲームオブジェクトの親として動作します。
6. Ctrl キー(Windows)または CMD キー(macOS)を押しながら、Hierarchy ウィンドウでそれぞれの Waypoints をクリックします。すべて選択したら、それらを Waypoints ゲームオブジェクト上にドラッグして親にします。
これでおしまい、敵を片付けてしまいましたね!
シーンを保存し、再生モードに切り替えて試してみましょう。終わったら、必ず再生モードを終了してください。
16. まとめ
このチュートリアルでは、ゲームの敵の作成を終えました。ほぼ完成しています!でも、ちょっと静かなんですよね。照明からのジーという音が気になりますが、雰囲気を盛り上げるにはもう少し音があってもいいと思います。次のチュートリアルでは、ゲームにオーディオを追加していきます。