ホラーゲームっぽい雰囲気になったところでいよいよ敵キャラを作って動かしてみましょう。
敵キャラのモデルのインポート
はじめに敵キャラのモデルをインポートします。今回は「True Horror – Scarecrow」というモデルを利用させていただきます。アセットストアから検索してダウンロードし、インポートしてください。
そうしたら、「True Horror」→「True_Scarecrow」に入っているモデルをシーンのヒエラルキーにドラッグ&ドロップしてください。
敵キャラのコンポーネントの設定
インポートしたモデルはそのままでは動かせないので、コンポーネントを追加したりして動かせる状態にする必要があります。
まずはアニメーションの設定です。とはいえ3Dのアニメーションを作るのは非常に大変なので、今回もスタンダードアセットに入っているアニメーションを使いましょう。「true_scarecrow」にアタッチされているAnimatorコンポーネントの「Controller」に、スタンダードアセットの「ThirdPersonAnimatorController」を指定してください(自分で探すよりも検索したほうがいいです)。
あとは下の画像のようにRigidbodyとCapsule Colliderをアタッチして値を適当に設定してください。
「追いかけてくる敵」をどう作るか?
さて、一通り設定が終わったところで敵キャラを動かせるようにしていきたいのですが、その前にちょっと考えることがあります。それはどうやったら敵キャラが主人公を上手く追いかけてくれるだろうか?ということです。
…え?「何言ってんだ、そんなの簡単だろう」って?…まあ、確かに「主人公の座標に向かって移動させる」だけならとても簡単でしょう。
しかしよく考えてください。障害物のない草原ならともかく、今回は入り組んだ地形での追いかけっこになります。このような場所で単純に主人公目指して移動させるだけだと、敵キャラがいとも簡単に地形に引っかかってしまいます。これではプレイヤーがちょっと上手く立ち回れば追いかけっこが成立しなくなり、つまらないゲームになってしまうことでしょう。
そこで今回の場合は
- 敵キャラが障害物や袋小路に引っかからずに主人公を追いかけられるか?
- どの道を通れば早く主人公を捕まえられるか?
といったことも考えなければなりません。実はこういった「経路探索」の分野は非常に難解であり、初心者がプログラミングするのは難しいです。…が、Unityには「NavMesh(ナビメッシュ)」という経路探索処理を簡単にする機能が備わっていますので、今回はありがたくこの機能を使わせてもらいましょう。
NavMeshの設定
NavMeshを使うには、まず床のオブジェクトにNavMeshを生成しておく必要があります。
まず、床のオブジェクトを選択して、オブジェクト名の右側にある「Static」にチェックを入れてください。これは一言で言うと、「このオブジェクトは動きません」というのを明示するためのオプションです(NavMeshを使う時だけでなく、ライティングなんかの設定をするときもチェックを入れたほうがいいときがあるかもしれません)。
次にメニューの「Window」→「Navigation」を選択すると、Navigationタブが開きます。床のオブジェクトを選択し、「Bake」を押してください。
そうするとNavMeshが生成されて、その部分が青く表示されるようになります。
NavMeshAgentの設定
NavMeshを設定できたら、次に敵キャラに「NavMeshAgent(ナビメッシュエージェント)」というコンポーネントをアタッチします。これはキャラクターにNavMeshを元にした経路探索や空間把握をさせる機能を追加するものです。
「true_scarecrow」オブジェクトをクリックし、「Add Component」→「Navigation」→「Nav Mesh Agent」を選択してください。そうしたら、下記の項目を調整してください。
- Speed:移動速度
- Angular Speed:旋回速度
- Acceleration:加速度
- Auto Braking:目的地の前で減速するかどうか。ここではオフにしてください。
追いかけてくる敵キャラのプログラム
とりあえず、Standard Assetsの中にあるAICharacterControllerを参考にしたプログラムを書いておきます。新しいC#スクリプトを作り、名前を「Enemy Controller」に変更して下記のソースコードを記入してください。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; using UnityStandardAssets.Characters.ThirdPerson; [RequireComponent(typeof(UnityEngine.AI.NavMeshAgent))] [RequireComponent(typeof(ThirdPersonCharacter))] public class EnemyController : MonoBehaviour { [SerializeField] Transform target; bool isActive = false; NavMeshAgent agent; ThirdPersonCharacter character; void Start () { agent = GetComponent<NavMeshAgent>(); character = GetComponent<ThirdPersonCharacter>(); agent.updateRotation = false; agent.updatePosition = true; isActive = true; } private void Update() { if (isActive) { if (target != null) agent.SetDestination(target.position); if (agent.remainingDistance > agent.stoppingDistance) { character.Move(agent.desiredVelocity, false, false); } else { character.Move(Vector3.zero, false, false); } } else { return; } } public void SetTarget(Transform target) { this.target = target; } void OnCollisionEnter(Collision other) { if(other.gameObject.tag == "Player") { Debug.Log("ゲームオーバーです。"); isActive = false; } } }
そうしたら、最後に敵キャラのオブジェクトにStandard Assetsの「Third Person Character」というスクリプトをアタッチしてください(検索したほうが速いです)。このとき設定項目の最後の「Ground Check Distance」を「0.3」くらいにしておきましょう(デフォルトの0.1だと接地判定が上手く行われず、キャラクターがアニメーションしません)。
障害物を追加する
さて、ここで本当に敵キャラが障害物を回避してくれるのかを確認しておきましょう。床の上に適当にCubeなどを作り、Staticにチェックを入れてもう一度NavMeshをベイクしてください。
テストプレイして敵キャラが障害物を迂回して向かってくれば成功です!