В этом примере есть два агента navmesh.
Один из них движется между путевыми точками. Второй достигает первой путевой точки, а затем останавливается и никогда не продолжает.
Я использую этот скрипт для генерации агентов navmesh и путевых точек:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InstantiateObjects : MonoBehaviour
{
public GameObject prefab;
public Terrain terrain;
public float yOffset = 0.5f;
public int objectsAmount;
public bool parent = true;
public bool randomScale = false;
public string tag;
public string name;
public Vector3 RandScaleMin;
public Vector3 RandScaleMax;
private float terrainWidth;
private float terrainLength;
private float xTerrainPos;
private float zTerrainPos;
private GameObject clonedObject;
private ObjectPool objectPool;
public void Start()
{
//Get terrain size
terrainWidth = terrain.terrainData.size.x;
terrainLength = terrain.terrainData.size.z;
//Get terrain position
xTerrainPos = terrain.transform.position.x;
zTerrainPos = terrain.transform.position.z;
generateObjectOnTerrain();
}
public void Update()
{
}
public void ReleaseObjects()
{
GameObject[] allobj = GameObject.FindGameObjectsWithTag(tag);
for (var i = 0; i < allobj.Length; i++)
{
objectPool.ReturnInstance(allobj[i]);
allobj[i].hideFlags = HideFlags.HideInHierarchy;
}
generateObjectOnTerrain();
}
public void generateObjectOnTerrain()
{
objectPool = new ObjectPool(prefab, objectsAmount);
for (int i = 0; i < objectsAmount; i++)
{
//Generate random x,z,y position on the terrain
float randX = UnityEngine.Random.Range(xTerrainPos, xTerrainPos + terrainWidth);
float randZ = UnityEngine.Random.Range(zTerrainPos, zTerrainPos + terrainLength);
float yVal = Terrain.activeTerrain.SampleHeight(new Vector3(randX, 0, randZ));
var randScaleX = Random.Range(RandScaleMin.x, RandScaleMax.x);
var randScaleY = Random.Range(RandScaleMin.y, RandScaleMax.y);
var randScaleZ = Random.Range(RandScaleMin.z, RandScaleMax.z);
var randVector3 = new Vector3(randScaleX, randScaleY, randScaleZ);
//Apply Offset if needed
yVal = yVal + yOffset;
clonedObject = objectPool.GetInstance();
if (randomScale == true)
clonedObject.transform.localScale = randVector3;//new Vector3(randScaleX, randScaleY, randScaleZ);
if (parent)
{
GameObject parent = GameObject.Find(name);
clonedObject.transform.parent = parent.transform;
}
clonedObject.tag = tag;
clonedObject.transform.position = new Vector3(randX, yVal, randZ);
}
}
}
И к каждому агенту navmesh я прилагаю этот скрипт:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class AgentControl : MonoBehaviour
{
public List<Transform> points = new List<Transform>();
public bool isInMeeting = false;
public float threshold = 3f;
public float strength = 5f;
private float speed;
private int destPoint = 0;
private NavMeshAgent agent;
private NavMeshAgent[] agents;
void Start()
{
agents = GameObject.FindObjectsOfType<NavMeshAgent>();
agent = GetComponent<NavMeshAgent>();
var agentsDestionations = GameObject.FindGameObjectsWithTag("Waypoint");
for (int i = 0; i < agentsDestionations.Length; i++)
{
points.Add(agentsDestionations[i].transform);
}
// Disabling auto-braking allows for continuous movement
// between points (ie, the agent doesn't slow down as it
// approaches a destination point).
agent.autoBraking = true;
agent.speed = Random.Range(10, 50);
speed = agent.speed;
GotoNextPoint();
}
void GotoNextPoint()
{
// Returns if no points have been set up
if (points.Count == 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.Count;
}
void Update()
{
float dist = Vector3.Distance(agent.transform.position, agents[1].transform.position);
if (dist < 5)
{
isInMeeting = true;
agents[1].GetComponent<AgentControl>().isInMeeting = true;
StartCoroutine(Meeting(agents[1]));
}
//Meeting();
// Choose the next destination point when the agent gets
// close to the current one.
if (!agent.pathPending && agent.remainingDistance < 2f)
{
if (isInMeeting == false)
GotoNextPoint();
}
}
private void Meeting()
{
//GameObject randomAgent = agents[Random.Range(0, agents.Length)];
/*if (Vector3.Distance(agent.transform.position, agents[1].transform.position) <= threshold)
{
isInMeeting = true;
StartCoroutine(Meeting(agents[1]));
}*/
}
IEnumerator Meeting(NavMeshAgent Agent)
{
var targetRotation = Quaternion.LookRotation(Agent.transform.position - transform.position);
var str = Mathf.Min(strength * Time.deltaTime, 1);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, str);
yield return new WaitForSeconds(10);
isInMeeting = false;
}
}
Вы можете игнорировать часть собрания, поскольку я никогда не включаю ее.
Это скриншот Иерархии во время игры, показывающий скрипт Инстанции Агентов в инспекторе:
* +1012 *
На этом снимке экрана показан Инспектор путевых точек:

Последний снимок экрана, на котором показан инспектор сценариев управления агентом:
* * 1030
И теперь оба агента остановились в первой точке пути и никогда не продолжили.
Иногда один из них продолжает перемещаться между путевыми точками, а другой остается в первой путевой точке.
Я хочу, чтобы они оба патрулировали между всеми путевыми точками.