多くのゲームには、ステージ内の巡回を自動的に行う NPC がいます。Unity のナビゲーションシステムでも、自動的に巡回する仕組みを実装することはできます。ですが、単純な2点間を巡回ルートの制限や予測なしで一直線に移動するような「一般的な」使い方よりも少し複雑になってしまいます。一種のシーケンスのような NPC が通過するために「便利」な巡回ポイントは、巡回パターンを決める材料になります。例えば、迷路ゲームでは道がつながっているかどうかを把握するために道の角ごとにエージェントが確認するための巡回ポイントを確保しなければいけません。例えば、オフィスビルでは巡回ポイントを各オフィスや部屋に配置しなければいけません。
一連の巡回ポイントの理想的な配置は、その NPC にどのように動いて欲しいかによって変わります。例えば、ロボットなら単純に、決まったポイントを決まった順番で巡回するでしょうが、人間の衛兵なら、プレイヤーを捕まえる為によりランダムなパターンで動くかもしれません。ロボットの単純な挙動は、下記のようなコードで実装することができます。
巡回ポイントは、スクリプトの public である Transform 配列として提供されています。GameObject のインスペクターからこの配列にアサインし、ポイントの位置をマーキングすることができます。 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();
}