【Unity】AI Navigationとは?キャラクターを範囲内で自動で移動させるシステム

AI Navigationとは? Unity

こんにちは、ともくんのゲーム作り部屋にようこそ!

このページでは、

「UnityのAI Navigationってなに?」

「AI Navigationでどんなことができるの?」

というお悩みの方に向けた内容となっています。

Unityでは、敵キャラクターやNPCなどの動きをAI Navigationというシステムで作ることができます。

このAI Navigationは、移動できる範囲を決めるNavMesh(ナビメッシュ)を設定することで、キャラクターを目的地まで自動で移動させることができるシステムです。

このシステムには、経路探索の「A*」と呼ばれるアルゴリズムが使用されていて、障害物があれば避けたりしながら、目的地までの道を自動で探してくれます。

そこでこのページでは、Unityで使うことができるAI Navigationというシステムについて、どんな機能なのか、また基本的な使い方をまとめていきます。

この記事を書いた人

ゲーム作りを学び始めた一児のパパです。
このブログは、子供から「ゲームを作ってみたい!」と言われ、非プログラマーでゲーム作りをしたことない僕が、ゲーム作りの本を読んで独学でゲーム開発を学んでいるブログです。
同じように初めてゲーム作りをしている方と一緒に学んでいけるようなブログに出来たらいいなと思っています。
また、「このコードはおかしい」とか「もっと良い書き方があるよ!」などあれば、どんどん指摘して頂けると助かります。

AI Navigationとは?エリア内でキャラクターを自動で動かす機能

まずは、AI Navigationがどういったシステムなのかを紹介していきます。

AI Navigationとは、シーン内で移動させたい範囲を指定してあげることで、キャラクターを目的地まで自動で移動させることができるシステムです。

このAI Navigationの仕組みとして、NavMesh(ナビメッシュ)と呼ばれる移動できる範囲の面をシーン内で作成しておくことで、特定のキャラクターやオブジェクトをそのNavMeshで指定したエリア内でのみ移動させることができるようになります。

そして、「A*」と呼ばれる経路探索アルゴリズムを使用することで、そのキャラクターやオブジェクトが現時点から目的地までの経路を自動的に探し、移動できるようになります。

このAI Navigationの機能を使うことで、

  • NPCキャラを特定の場所まで自動で移動させる
  • 敵キャラをプレイヤーがいる位置に向かって移動させる

などのことが、簡単に設定できるようになります。

AI Navigationの基本的な使い方

ここからは、AI Navigationの基本的な使い方について紹介していきます。

移動させたい範囲に「NavMesh Surface」を付ける

まずは、AI Navigationを使って移動させたい範囲となるNavMeshを作っていきます。

このNavMeshを作る場合は、その範囲となるオブジェクトに対して、NavMesh Surfaceというコンポーネントを紐づけていきます。

ここでは、実際に以下のようなキューブを組み合わせた簡単な通路をNavMeshとしてみます。

それぞれのキューブをRoadという空オブジェクトの階層に入れて、このRoadを選択した状態でインスペクターウィンドウの「AddComponent」から、「Navigation」にある「Nav Mesh Surface」を選択します。

これで指定した範囲のキューブに、NavMesh Surfaceを設定することができました。

NavMeshを「ベイク」する

NavMeshを作成する際は、NavMesh Surfaceからベイクする必要があります。

このベイクとは、指定した範囲をキャラクターが移動できるように、事前に地形などから移動範囲を計算しておく機能のことです。

ベイクする場合は、先ほどのRoadの親オブジェクトを選択して、NavMesh Surfaceコンポーネントの中にある「Bake」をクリックします。

すると、シーン内の通路の部分が水色に表示されるようになります。

この水色で表示されている部分がNavMeshで、この範囲の中でキャラクターを動かすことができるようになります。

なお、ベイクしても水色に表示されない場合は、シーン内のアイコンから「AI Navigation」のツールを開き、「Show NavMesh」にチェックを入れておきましょう。

また、ベイクはあくまでも事前に行う計算となるので、通路を増やしたり変更した場合は再度ベイクしないとNavMeshの範囲とならないため、注意しておきましょう。

移動させるオブジェクトに「NavMesh Agent」を付ける

NavMeshを作成することができたら、今度は移動させるキャラクターやオブジェクトを準備していきます。

NavMeshの上で動かしたいオブジェクトには、NavMesh Agentというコンポーネントを紐づけていきます。

ここでは、キャラクターでは無いですが、球体のオブジェクトを作成して、このオブジェクトがキューブで作った通路内を移動できるようにしていきます。

球体のオブジェクトを選択した状態で、インスペクターウィンドウの「AddComponent」から、「Navigation」にある「Nav Mesh Agent」を選択します。

このボールに対して、一旦キーボード操作から動かせるように、以下のスクリプトをアタッチしておきます。

using UnityEngine;

public class Test : MonoBehaviour
{
    float speed = 0.03f;

    void Update()
    {
        if (Input.GetKey(KeyCode.UpArrow))
        {
            transform.Translate(0, 0, speed);
        }
        else if (Input.GetKey(KeyCode.DownArrow))
        {
            transform.Translate(0, 0, -speed);
        }
        else if (Input.GetKey(KeyCode.LeftArrow))
        {
            transform.Translate(-speed, 0, 0);
        }
        else if (Input.GetKey(KeyCode.RightArrow))
        {
            transform.Translate(speed, 0, 0);
        }
    }
}

これで実際にゲームを実行してみると、

キー操作でボールを動かすことができますが、NavMeshの範囲外には移動できないのが分かります。

つまり、NavMesh Agentが付いているオブジェクトは、NavMesh上しか移動できない状態になります。

「SetDestinationメソッド」で指定場所まで自動で移動させる

NavMesh Agentのオブジェクトを自動で移動させる場合は、SetDestinationメソッドを使います。

このSetDestinationメソッドは、指定した目的地に対して、NavMeshの範囲を使って経路を自動で探索して移動する処理を行うメソッドで、NavMesh Agentコンポーネントで定義されています。

ここでは、SetDestinationメソッドを使ってマウスでクリックした場所に向かって、ボールが自動で移動する仕組みを作ってみます。

using UnityEngine;
using UnityEngine.AI;   // AI Navigationをスクリプトから使用する際に記述

public class Test : MonoBehaviour
{
    NavMeshAgent agent;

    void Start()
    {
        agent = GetComponent<NavMeshAgent>();   // NavMeshAgentを取得する
    }

    void Update()
    {
        // マウスをクリックした場合
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);    // カメラからマウスカーソルの位置に向かうRay
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit))  // Rayを飛ばしてオブジェクトとの衝突判定
            {
                agent.SetDestination(hit.point);    // マウスカーソルの位置に向かって自動で移動させる処理
            }
        }
    }
}

まず、スクリプトからAI Navigationを使用する場合には、スクリプトの2行目のように利用する記述が必要となります。

また、SetDestinationメソッドを使う際は、NavMesh Agentコンポーネントを取得する必要があるため、10行目のStartメソッドの中でGetComponentで取得しています。

次に、マウスをクリックした処理の中で、20行目にPhysics.Raycastメソッドを使ってマウスでクリックしたオブジェクトとの衝突判定を行っています。

今回は、キューブオブジェクトとの衝突判定を行う必要があるため、全てのキューブにコライダーコンポーネントを付けています。

そして、Raycastで衝突判定がtrueだった場合の中の22行目で、SetDestinationメソッドを使い目的地を指定しています。

SetDestinationメソッドは、以下のように引数に目的地の場所をVector3型で指定することで、オブジェクトがその場所に向かって自動的に移動する処理が行われます。

NavMeshAgent.SetDestination(目的地点);

ここでは、目的地点をマウスでクリックした場所にしたいので、Raycastの中で取得したhit変数を使って「hit.point」と指定しています。

これでゲームを実行してみると、

マウスでクリックした場所に向かって、ボールが自動的に通路内を動くようになりました。

なお、ボールの速度が遅い場合は、NavMesh Agentコンポーネントの項目の「Speed」の値を変えて上げることで、速度が変更できます。(今回は「8」で設定しています。)

まとめ

このページでは、UnityのAI Navigationについて、どんな機能なのか、特徴や基本的な使い方までをまとめていきましたが、いかがでしたでしょうか?

AI Navigationとは、指定した範囲の中で目的地点に向かって経路を検索して、キャラクターやオブジェクトを自動で移動させることができるシステムです。

このAI Navigationを使うことで、特定の範囲を動く敵やNPCなどのキャラクターの動きを自動で作ることができます。

また、障害物などを配置しておくことで、それを避けて移動させることもできます。

最後までお読みいただきまして、ありがとうございました!

コメント