マウスでクリックした位置へエージェントを移動させる
アニメーションとナビゲーションの組み合わせ

エージェントに設定した地点を巡回させる

多くのゲームには、プレイエリアの巡回を自動的に行うノンプレイヤーキャラクター (NPC) 機能があります。Unity のナビゲーションシステムを使用すると、このような機能を実装することができます。ただし、単に 2 点間の最短の経路を使用して、制限された予測可能な巡回ルートを作るような一般的な経路の作成よりも少し複雑なものです。NPC が、ある種の順序で通過したり立ち寄ったりするために役に立つ、いくつかのキーとなる地点を設けることによって、より納得のいく巡回パターンを設定することができます。例えば、迷路では、交差点と曲がり角に巡回のキーとなる地点を置き、エージェントがそこですべての通路を確認するようにできます。オフィスビルでは、キー地点を個々のオフィスや部屋に置くこともできます。

巡回のキー地点を記した迷路
巡回のキー地点を記した迷路

巡回地点の理想的な順序は、その NPC にどのように動いて欲しいかによって変わります。例えば、ロボットなら単純に、決まった順番で決められた地点を巡回するでしょう。一方、人間の警備員なら、プレイヤーを捕まえるためによりランダムなパターンで動くかもしれません。ロボットの単純な挙動は、下のようなコードで実装することができます。

巡回地点は、Transform の public の配列を使ってスクリプトに渡されます。地点の位置を示すため、この配列はゲームオブジェクトを使ってインスペクターから割り当てられます。GotoNextPoint 関数はエージェントの目標地点を設定し(この関数はエージェントの移動も開始します)、それから、次の呼び出しで使用される新しい目標地点を選択します。現状では、コードは配列内の順番通りに地点を巡回するようになっていますが、これは簡単に修正可能です。例えば Random.Range を使用すると、配列のインデックスはランダムに選択されます。

Update 関数では、スクリプトは remainingDistance プロパティーを使用してエージェントから目標地点までの距離を確認します。これがごく短い場合は GotoNextPoint の呼び出しが行われて次の地点への巡回が開始されます。

    // Patrol.cs
    using UnityEngine;
    using UnityEngine.AI;
    using System.Collections;


    public class Patrol : MonoBehaviour {

        public Transform[] points;
        private int destPoint = 0;
        private NavMeshAgent agent;


        void Start () {
            agent = GetComponent<NavMeshAgent>();

            // Disabling auto-braking allows for continuous movement
            // between points (ie, the agent doesn't slow down as it
            // approaches a destination point).
            agent.autoBraking = false;

            GotoNextPoint();
        }


        void GotoNextPoint() {
            // Returns if no points have been set up
            if (points.Length == 0)
                return;

            // Set the agent to go to the currently selected destination.
            agent.destination = points[destPoint].position;

            // Choose the next point in the array as the destination,
            // cycling to the start if necessary.
            destPoint = (destPoint + 1) % points.Length;
        }


        void Update () {
            // Choose the next destination point when the agent gets
            // close to the current one.
            if (!agent.pathPending && agent.remainingDistance < 0.5f)
                GotoNextPoint();
        }
    }
    // Patrol.js
        var points: Transform[];
        var destPoint: int = 0;
        var agent: NavMeshAgent;


        function Start() {
            agent = GetComponent.<NavMeshAgent>();

            // autoBraking を無効にすると、目標地点の間を継続的に移動します
            // (つまり、エージェントは目標地点に近づいても
            // 速度をおとしません)
            agent.autoBraking = false;

            GotoNextPoint();
        }


        function GotoNextPoint() {
            // 地点がなにも設定されていないときに返します
            if (points.Length == 0)
                return;

            // エージェントが現在設定された目標地点に行くように設定します
            agent.destination = points[destPoint].position;

            // 配列内の次の位置を目標地点に設定し、
            // 必要ならば開始にもどります
            destPoint = (destPoint + 1) % points.Length;
        }


        function Update() {
            // エージェントが現目標地点に近づいてきたら、
            // 次の目標地点を選択します
            if (!agent.pathPending && agent.remainingDistance < 0.5f)
                GotoNextPoint();
        }
マウスでクリックした位置へエージェントを移動させる
アニメーションとナビゲーションの組み合わせ