转自:https://blog.youkuaiyun.com/qq_37724011/article/details/115184131
问题:在unity使用navmeshAgent进行多人寻路设置同一个终点后,所有角色都会向对应位置寻路,当前面单位到达后后面单位会一直无法到达导致阻塞甚至推挤。
简单的解决方案是给自己同时挂上navmeshAgent组件和navmeshObstacle组件,注意两个组件不能同时开启,否则会躲避自身导致胡乱移动。
在移动时关闭navmeshObstacle,使用navmeshAgent进行寻路。而达到目的地后则先关闭navmeshAgent,然后打开navmeshObstacle并开启carve属性,就会在寻路网格上挖洞,后来的单位则会重新寻路到附近可以走得地方就不会卡死了。
在攻击时使用这个解决方案也可以让后来得角色包围目标而不是挤在一起。
对应代码:
navMeshAgent.enabled = false;
navMeshObstacle.enabled = true;
navMeshObstacle.carving = true;
然后再要再次移动时再关闭挖洞,然后再打开寻路即可。
聪明的你应该猜到并写下了这么一段代码:
navMeshObstacle.enabled = false;
navMeshObstacle.carving = false;
navMeshAgent.enabled = true;
但是这其中有个问题:就表现上来说,角色会瞬移到之前挖好的洞旁边。看起来无法接受。
其中的原因是什么呢?
是因为这是在同一帧执行的,虽然写了关闭挖洞,但是在还没来得及真正的关闭挖洞就又打开了navmeshAgent,此时navmeshAgent判断自己不在寻路网格上,于是把自己移动到最近的寻路网格上就导致了顺义。
解决办法就是分为两帧执行,在一般的逻辑中这完全是可以接受的,因为从静止到移动确实需要花一些时间。
我因为是用了行为树所以写在了类似update的函数中,每次都会执行。你也可以直接改成协程。
private int frmeCount=0;
void Update(){
if (frameCount == 1)//分为第0帧和第一帧,在关闭navmeshObstacle后的下一帧再开启navmeshAgent
{
navMeshAgent.enabled = true;
}
else
{
navMeshObstacle.carving = false;
navMeshObstacle.enabled = false;
frameCount=1;
}
}
当然,上面只是一段伪代码,自己注意启用条件之类的吧。
此外:如果你想各个单位能够更好的到达终点则每个单位的终点并不应该设置为同一个点,你可能需要根据每个角色的寻路半径来预先随机设置每个角色会到达的对应的位置,这样在寻路时才不会互相推挤。