見出し画像

[Unity]NavMeshで追いかけられてみた

こんにちは! エンジニアの宮Pです😎
今回はUnityのNavMesh機能を使って、プレイヤーを自動的に追いかける敵キャラクターの動きを作ってみます。

はじめに

『パックマン』のような俯瞰型の2Dゲームにも、『バイオハザード』のような一人称(または三人称)視点の3Dゲームにも、プレイヤーキャラクターを執拗に追いかける敵が存在します。
しかも彼らは「障害物を避けて回り込む」なんていう賢さも持っていますね。
NavMeshという機能を使うことで、こうした敵の移動プログラムを簡単に作ることができます🙂

新規プロジェクトを作る

まずは新規のUnityプロジェクトを用意します。
Unity Hubで「新しいプロジェクト」を選んで、3Dのテンプレートを選びます。
今回はWindowsでテストをしていますが、スマホで動かしてみたい方は過去の記事などを参考に詳細設定を進めてください。

フィールドを用意する

プレイヤーと敵が移動するフィールドを作ります。
まず3D Object の Plane を配置して床を作ります。
追いかけ回す様子が分かるようにScaleをそれぞれ「2」に増やして、少し広めのフィールドを用意しました。

次に障害物を設置します。
Scaleが X=3、Y=1、Z=1 の Cubeを用意し、 これをコピーして適当な場所に並べます(大きさや数は好みに応じて変えて増減させてください)。
CubeのY座標を0.5にして、床にピッタリ貼り付くようにしています。

プレイヤーと敵を用意する

まずは追いかけられる側のプレイヤーキャラクターを用意します。
Asset StoreからUnityちゃんアセットを入手し、これをインポートします。

すべての要素をインポートしておきます

次は追いかけ回してくる敵キャラクターを用意します。
Asset Storeで「Level 1 Monster」を検索して、この無料のアセットをインポートしてください。

Asset Store側で[Open in Unity]ボタンを押しても、Unity側にインポートされないことがあるようです。
Unityの公式ページによると「プロキシ、ファイアウォール、ウイルス対策ソフトなどが影響することがある」とのこと。
こんな場合には、次の方法でのインポートを試してみてください。

UnityのWindowメニューからPackage Managerを開きます。
「Packages:」をMy Assetsに変更します。
これまでに入手したアセットが表示されるので、この中から「Level 1 Monster Pack」を選択して、[Import]ボタンをクリックします。

インポートの確認ウィンドウが開いたら、Unityちゃんの時と同様に[Import]ボタンをクリックします。

こちらもすべての要素をインポートしておきます

インポートが終わったら、UnityちゃんとモンスターのPrefabを適当な場所に配置します。
モンスターのモデルはとても小さいので、Scaleを30~35くらいの値にしてやるとUnityちゃんとバランスが取れるようです🤔

移動可能な領域をBakeする

NavMeshを使って移動可能な領域を算出することを「Bake(ベイク)」すると言います。いよいよ、このBake作業に入ります。

WindowsメニューからPackage Managerを開きます。
「Packages:」をUnity Registoryに変更して「AI Navigation」を検索します。
見つかったら、このアセットをインストールします。

正常にインストールされると、Windowsメニューに「AI」という項目が増えます。
今回の作業では必須ではないのですが、このAIメニューのNavigationを選択してみます。

こんなウィンドウが開きます。
NavMeshでは細かなパラメータを設定してAIの調整ができます。
これらのパラメータもその1つですが、個々に説明しているとかなりの長文になってしまうので、今回はデフォルト値のままにしておきます。

Bake用のゲームオブジェクトを作ります。
ヒエラルキーを右クリックして、AIメニューのNavMesh Surfaceを選択します。

このNavMesh SurfaceのインスペクターでAdd Componentを確認すると、色々と追加可能なコンポーネントが用意されていることが分かります。
この中のNavMesh Surfaceを追加します。
さらにモンスターのインスペクターにNav Mesh Agentコンポーネントを追加します。

インスペクターの右下の[Bake]ボタンをクリックすると、画面が以下のように変化します🙂

BakeボタンはNavMesSurfaceの一番下です

この水色部分は「通行可能な領域」として認識されており、それ以外の部分は「通行不可」となります。
ピンク色の障害物、外周が自動的に検出されて「通行不可」となっています。外周を進むと落っこちてしまうこともあるので、このままで問題なさそうです。

制御用スクリプトを書く

Unityちゃんを操作したり、敵が目標を目掛けて移動するためのスクリプトを書いていきます。

まずはUnityちゃんを動かすためのスクリプトを作って、ヒエラルキー上のUnityちゃんに貼りつけます。

■ PlayerControl.cs

using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour {
    public float Speed = 30.0f;      //移動速度 m/s 
    private Animator animator;

    void Start() {
        // UnityちゃんのAnimatorを取得
        animator = GetComponent<Animator>();
        if (animator != null) {
            // アニメーションを無効化してポーズを固定
            animator.enabled = false;
        }
    }

     void Update() { 
        Vector3 pos = transform.position; 
        float moveLength = Speed * 2 * Time.deltaTime;

        if (Input.GetKey(KeyCode.UpArrow)) { 
            pos.z += moveLength; 
        } else if (Input.GetKey(KeyCode.DownArrow)) { 
            pos.z -= moveLength; 
        } else if(Input.GetKey(KeyCode.LeftArrow)) { 
            pos.x -= moveLength; 
        } else if(Input.GetKey(KeyCode.RightArrow)) { 
            pos.x += moveLength; 
        } 
        transform.position = pos; 
    }
}

次に敵を動かすためのスクリプトを作って、ヒエラルキー上のモンスターに貼りつけます。
インスペクターの「Player」は敵が追いかける目標です。デフォルトでは「none」になっているので、ここにヒエラルキー上のUnityちゃんをドラッグ&ドロップしてください。

■ EmemyMove.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class EnemyMove : MonoBehaviour
{
    // 追いかける対象のゲームオブジェクト
    [SerializeField]
    private GameObject player;

    // NavMeshAgentコンポーネントを入れる
    private NavMeshAgent navMesAgent;

    // Start is called before the first frame update
    void Start()
    {
        // 自分自身のNavMeshAgentを入れる
        navMesAgent = this.gameObject.GetComponent<NavMeshAgent>();
    }

    // Update is called once per frame
    void Update()
    {
        // 目的地をプレイヤーにする
        navMesAgent.destination = player.transform.position;
    }
}

実行すると、モンスターは途中にある壁を避けつつ、その向こうのUnityちゃんを認識して移動しています😉

今度はUnityちゃんを動かしてみます。
NavMeshの賢いところは、目的となる対象物が移動していると、そこへ向かうルートを動的に計算してくれるところです🙂

まとめ

NavMeshの基本機能を使って、対象物を追いかけるサンプルを作ってみました。
ホントに必要な部分だけを使って作ったので、Unityちゃんがアニメーションしてなかったり、上のサンプルのままでは障害物をすり抜けることが出来たり…😓

NavMeshは結構細かい指定ができるので、上手く使うと面白いことができます。
例えば「少しの段差なら敵が乗り越えてくる」とか、「自分は入れないけど、敵は通過できる場所」とか。
ゲームのルールに応じてAIを調整して、より複雑な性格付けも可能です。

久々にNavMeshを触って楽しかったので、次回はこの機能を使ったゲーム作りなんかもやってみようと考えています😊

私たちは、お客様のご要望にあわせて様々なコンテンツ、アプリを制作いたします。
ご質問やご要望は、<お問い合わせページ>よりお送りください。





この記事が気に入ったらサポートをしてみませんか?