多くのゲームには、プレイエリアの巡回を自動的に行うノンプレイヤーキャラクター (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>();
// autoBraking を無効にすると、目標地点の間を継続的に移動します
// (つまり、エージェントは目標地点に近づいても
// 速度をおとしません)
agent.autoBraking = false;
GotoNextPoint();
}
void GotoNextPoint() {
// 地点がなにも設定されていないときに返します
if (points.Length == 0)
return;
//エージェントが現在設定された目標地点に行くように設定します
agent.destination = points[destPoint].position;
// 配列内の次の位置を目標地点に設定し、
// 必要ならば開始にもどります
destPoint = (destPoint + 1) % points.Length;
}
void Update () {
// エージェントが現目標地点に近づいてきたら、
//次の目標地点を選択します
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();
}