Unity-在一組點(diǎn)之間進(jìn)行代理巡邏
許多游戲都有 NPC 負(fù)責(zé)在游戲區(qū)域周?chē)詣?dòng)巡邏。使用導(dǎo)航系統(tǒng)可實(shí)現(xiàn)此行為,但它比標(biāo)準(zhǔn)尋路方法稍微復(fù)雜一些;標(biāo)準(zhǔn)尋路方法僅使用兩點(diǎn)之間的最短路徑就可以實(shí)現(xiàn)有限且可預(yù)測(cè)的巡邏路線。為獲得更有說(shuō)服力的巡邏模式,可保留一組“有用”的關(guān)鍵點(diǎn)讓 NPC 以某種順序通過(guò)并訪問(wèn)它們。例如,在迷宮中,可將關(guān)鍵巡邏點(diǎn)放置在交叉點(diǎn)和拐角處,從而確保代理檢查每個(gè)走廊。對(duì)于辦公樓,關(guān)鍵點(diǎn)可能是各個(gè)辦公室和其他房間。

理想的巡邏點(diǎn)序列將取決于所需的 NPC 行為方式。例如,機(jī)器人可能只是按照有條不紊的順序訪問(wèn)這些點(diǎn),而人類守衛(wèi)可能會(huì)嘗試通過(guò)使用更隨機(jī)的模式來(lái)發(fā)現(xiàn)玩家??墒褂孟旅骘@示的代碼實(shí)現(xiàn)機(jī)器人的簡(jiǎn)單行為。
應(yīng)使用公共變換數(shù)組將巡邏點(diǎn)提供給腳本??蓮臋z視面板分配此數(shù)組,并使用游戲?qū)ο髞?lái)標(biāo)記巡邏點(diǎn)的位置。GotoNextPoint?函數(shù)可設(shè)置代理的目標(biāo)點(diǎn)(也開(kāi)始移動(dòng)代理),然后選擇將在下次調(diào)用時(shí)使用的新目標(biāo)。就目前而言,該代碼將按照巡邏點(diǎn)在數(shù)組中出現(xiàn)的順序循環(huán)遍歷巡邏點(diǎn),但您可以輕松修改這種設(shè)置,例如使用?Random.Range?來(lái)隨機(jī)選擇數(shù)組索引。
在?Update?函數(shù)中,該腳本使用?remainingDistance?屬性檢查代理與目標(biāo)的接近程度。當(dāng)此距離非常小時(shí),將調(diào)用?GotoNextPoint?來(lái)啟動(dòng)巡邏的下一段。
// 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>();
? ? ? ? ? ? ? ?
// 禁用自動(dòng)制動(dòng)將允許點(diǎn)之間的
? ? ? ? ? ? ? ?
// 連續(xù)移動(dòng)(即,代理在接近目標(biāo)點(diǎn)時(shí)
? ? ? ? ? ? ? ?
// 不會(huì)減速)。
? ? ? ? ? ? ? ?
agent.autoBraking = false;
? ? ? ? ? ? ? ?
GotoNextPoint();
? ? ? ? ? ?
}
? ? ? ? ? ?
void GotoNextPoint() {
? ? ? ? ? ? ? ?
// 如果未設(shè)置任何點(diǎn),則返回
? ? ? ? ? ? ? ?
if (points.Length == 0)
? ? ? ? ? ? ? ? ? ?
return;
? ? ? ? ? ? ? ?
//將代理設(shè)置為前往當(dāng)前選定的目標(biāo)。
? ? ? ? ? ? ? ?
agent.destination = points[destPoint].position;
? ? ? ? ? ? ? ?
//選擇數(shù)組中的下一個(gè)點(diǎn)作為目標(biāo),
? ? ? ? ? ? ? ?
// 如有必要,循環(huán)到開(kāi)始。
? ? ? ? ? ? ? ?
destPoint = (destPoint + 1) % points.Length;
? ? ? ? ? ?
}
? ? ? ? ? ?
void Update () {
? ? ? ? ? ? ? ?
//當(dāng)代理接近當(dāng)前目標(biāo)點(diǎn)時(shí),
? ? ? ? ? ? ? ?
// 選擇下一個(gè)目標(biāo)點(diǎn)。
? ? ? ? ? ? ? ?
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>();
? ? ? ? ? ?
// 禁用自動(dòng)制動(dòng)將允許點(diǎn)之間的
? ? ? ? ? ?
// 連續(xù)移動(dòng)(即,代理在接近目標(biāo)點(diǎn)時(shí)
// 不會(huì)減速)。
? ? ? ? ? agent.autoBraking = false;
? ? ? ? ? ?
GotoNextPoint();
? ? ? ?
}
? ? ? ?
function GotoNextPoint() {
? ? ? ? ? ?
// 如果未設(shè)置任何點(diǎn),則返回
? ? ? ? ? ?
if (points.Length == 0)
? ? ? ? ? ? ? ?
return;
? ? ? ? ? ?
? ? ? ? ? ?
//將代理設(shè)置為前往當(dāng)前選定的目標(biāo)。
? ? ? ? ? ?
agent.destination = points[destPoint].position;
? ? ? ? ? ?
//選擇數(shù)組中的下一個(gè)點(diǎn)作為目標(biāo),
? ? ? ? ? ?
// 如有必要,循環(huán)到開(kāi)始。
? ? ? ? ? ?
destPoint = (destPoint + 1) % points.Length;
? ? ? ?
}
? ? ? ?
function Update() {
? ? ? ? ? ?
//當(dāng)代理接近當(dāng)前目標(biāo)點(diǎn)時(shí),
? ? ? ? ? ?
// 選擇下一個(gè)目標(biāo)點(diǎn)。
? ? ? ? ? ?
if (!agent.pathPending && agent.remainingDistance < 0.5f)
? ? ? ? ? ? ? ?
GotoNextPoint();
? ? ? ?
}