Why Cache Path
- in my game, the map is never change when created
- each time , i need create 300~400 unit at point A, and ask them move to point B (with RVO)
How To
- use
ABPath.Construct
to request a path instance Claim
the path- use
richAI.SetPath
in the loop to set the path directly
Full Code
using System.Collections;
using System.Collections.Generic;
using Pathfinding;
using UnityEngine;
using UnityEngine.UI;
public class NavTest1 : MonoBehaviour
{
public Button cachePathGenBtn;
public Button normalGenBtn;
public Toggle isUseEnumerator;
public int agentNum;
public GameObject Agent;
public Transform startPos;
public Transform aimTarget;
private Path mPath;
private bool mIsNotTick;
private void Start()
{
cachePathGenBtn.onClick.AddListener(OnClickCacheGenWithEnumeratorBtn);
normalGenBtn.onClick.AddListener(OnClickNormalGen);
}
private void OnClickCacheGenWithEnumeratorBtn()
{
if (mPath == null)
{
mPath = ABPath.Construct(startPos.position, aimTarget.position, (p) => { Debug.Log($"Not useful because Path PipelineState = {p.PipelineState} not PathState.Returned"); });
AstarPath.StartPath(mPath);
mIsNotTick = false;
}
else
{
if (isUseEnumerator.isOn)
{
StartCoroutine(CacheGenWithEnumerator());
}
else
{
CacheGenDirectly();
}
}
}
private void OnClickNormalGen() { NormalGen(); }
private void Update()
{
if (mPath == null || mIsNotTick) return;
if (mPath.PipelineState == PathState.Returned)
{
mIsNotTick = true;
mPath.Claim(this);
var m = new StartEndModifier();
m.Apply(mPath);
if (isUseEnumerator.isOn)
{
StartCoroutine(CacheGenWithEnumerator());
}
else
{
CacheGenDirectly();
}
}
}
private void NormalGen()
{
for (int i = 0; i < agentNum; i++)
{
var agentGo = Instantiate(Agent, GetRanStartPos(), Quaternion.identity);
agentGo.GetComponent<RichAI>().destination = aimTarget.position;
}
}
private IEnumerator CacheGenWithEnumerator()
{
yield return null;
var list = new List<RichAI>();
for (var i = 0; i < agentNum; i++)
{
var agentGo = Instantiate(Agent, GetRanStartPos(), Quaternion.identity);
list.Add(agentGo.GetComponent<RichAI>());
}
yield return null;
list.ForEach(richAI => richAI.SetPath(mPath));
}
private void CacheGenDirectly()
{
for (var i = 0; i < agentNum; i++)
{
var agentGo = Instantiate(Agent, GetRanStartPos(), Quaternion.identity);
agentGo.GetComponent<RichAI>().SetPath(mPath);
}
}
private Vector3 GetRanStartPos()
{
var b = startPos.position;
b.x += Random.Range(-0.1f, 0.1f);
b.z += Random.Range(-0.1f, 0.1f);
return b;
}
}
Issue
ABPath.Construct callback not working on multi-thread
mPath = ABPath.Construct(startPos.position, aimTarget.position, (p) => { Debug.Log($"Not useful because Path PipelineState = {p.PipelineState} not PathState.Returned"); });
output:
Not useful because Path PipelineState = ReturnQueue not PathState.Returned
in RichAI.cs
SetPath
function , it only accept PathState.Created
or PathState.Returned
so ,in my previous code . i use the Update
function to wait it finish
Create agent at exact same position RVO will not working
private Vector3 GetRanStartPos()
{
var b = startPos.position;
b.x += Random.Range(-0.1f, 0.1f);
b.z += Random.Range(-0.1f, 0.1f);
return b;
}
for (int i = 0; i < agentNum; i++)
{
var agentGo = Instantiate(Agent, GetRanStartPos(), Quaternion.identity);
agentGo.GetComponent<RichAI>().destination = aimTarget.position;
}
if just Instantiate all agent at same position same frame. all agent will follow the path without RVO.
Some agent not move with no error.
private IEnumerator CacheGenWithEnumerator()
{
yield return null;
var list = new List<RichAI>();
for (var i = 0; i < agentNum; i++)
{
var agentGo = Instantiate(Agent, GetRanStartPos(), Quaternion.identity);
list.Add(agentGo.GetComponent<RichAI>());
}
yield return null;
list.ForEach(richAI => richAI.SetPath(mPath));
}
private void CacheGenDirectly()
{
for (var i = 0; i < agentNum; i++)
{
var agentGo = Instantiate(Agent, GetRanStartPos(), Quaternion.identity);
agentGo.GetComponent<RichAI>().SetPath(mPath);
}
}
when try to use cache path create 100 agents, some of them (around 20) can follow the path to move.
reset of them not move at all. and i can’t find any error output in my Console. (A* log level already set to heavy)
if i use normal gen function, everything work fine
private void NormalGen()
{
for (int i = 0; i < agentNum; i++)
{
var agentGo = Instantiate(Agent, GetRanStartPos(), Quaternion.identity);
agentGo.GetComponent<RichAI>().destination = aimTarget.position;
}
}
Demo Project
Unity : 2019.3.3f1
Burst: 1.2.3
A*Project: 4.3.14