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

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

多くのゲームには、プレイエリアの巡回を自動的に行うノンプレイヤーキャラクター (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();
        }
マウスでクリックした位置へエージェントを移動させる
アニメーションとナビゲーションの組み合わせ