多くのゲームには、プレイエリアの巡回を自動的に行うノンプレイヤーキャラクター (NPC) 機能があります。Unity のナビゲーションシステムを使用すると、このような機能を実装することができます。ただし、単に 2点間の最短の経路を使用して、制限された予測可能な巡回ルートを作るような一般的な経路の作成よりも少し複雑なものです。NPC が、ある種の順序で通過したり立ち寄ったりするために役に立つ、いくつかのキーとなる地点を設けることによって、より納得のいく巡回パターンを設定することができます。例えば、迷路では、交差点と曲がり角に巡回のキーとなる地点を置き、エージェントがそこですべての通路を確認するようにできます。オフィスビルでは、キー地点を個々のオフィスや部屋に置くこともできます。
巡回地点の理想的な順序は、その NPC にどのように動いて欲しいかによって変わります。例えば、ロボットなら単純に、決まった順番で決められた地点を巡回するでしょう。一方、人間の警備員なら、プレイヤーを捕まえるためによりランダムなパターンで動くかもしれません。ロボットの単純な挙動は、下のようなコードで実装することができます。
巡回地点は、Transform の public の配列を使ってスクリプトに渡されます。地点の位置を示すため、この配列はゲームオブジェクトを使ってインスペクターから割り当てられます。GotoNextPoint 関数はエージェントの目標地点を設定し(この関数はエージェントの移動も開始します)、それから、次の呼び出しで使用される新しい目標地点を選択します。現状では、コードは配列内の順番通りに地点を巡回するようになっていますが、これは簡単に修正可能です。例えば Random.Range を使用すると、配列のインデックスはランダムに選択されます。
Update 関数では、スクリプトは remainingDistance プロパティーを使用してエージェントから目的地までの残りの道程の長さを確認します。この道程の長さがごく短い場合は GotoNextPoint への呼び出しが行われて次の巡回行程が開始されます。
// Patrol.cs
using UnityEngine;
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.remainingDistance < 0.5f)
GotoNextPoint();
}
}
// Patrol.js
var points: Transform[];
var destPoint: int = 0;
var agent: NavMeshAgent;
function 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();
}
function 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;
}
function Update() {
// Choose the next destination point when the agent gets
// close to the current one.
if (agent.remainingDistance < 0.5f)
GotoNextPoint();
}