您的位置:首页 > 其它

我的游戏开发笔记(六):NavMeshAgent及自动寻径(跳跃)。

2015-09-02 18:43 1266 查看
相信只要用过unity3d4.0以上都都会用过NavMeshAgent这个组件,这是一个十分强大的寻路组件,只要对地形进行bake,然后设置一个目标点,就可以实现高效率的寻路了。

可是unity3d自带的AI用NavMeshAgent寻路,只有跑步走路,若我想跳跃蹲下瞬移怎么办?

在上一篇文章中提到的 Unity手游之路<十>自动寻路Navmesh之跳跃,攀爬,斜坡 虽然很好的实现了这些功能,但是该作者使用的Animation,而我要使用Animator对角色的动作的改变。只能再进一步研究NavMeshAgent了。

一:无空间间隔的寻路

首先,想要角色在自动寻路时进行跳跃,那必须给他个判断条件吧?第一个想到的肯定是设置一个触发开关,当角色寻径到这个地点的时候就把m_Jump设为true就行了。

private void Update()
{
if (target != null)
{
agent.SetDestination(target.position);
character.Move(agent.desiredVelocity, false, m_Jump,false,false,false,false,false,false,false);
}
else
{
character.Move(Vector3.zero, false, m_Jump,false,false,false,false,false,false,false);
}
m_Jump = false;
}

void OnTrrigerEnter(Collider co)
{
if (co.tag == "Jump!")
{
m_Jump = true;
}
}


然后我发现,角色只会执行跳跃这个动作而不会跳起来,如下图(看不出来,反正就是在地上滚了一圈,本来应该是跳起来在天上滚的)



从这里可以推断出,若使用NavMeshAgent来寻路,角色的y轴被锁定在了NavMesh面,也就是bake后从Navigation看到的蓝色的那层,不可改变。

有了这个推断,若用NavMeshAgent自动寻路,y轴会被锁定,反过来说,若不用NavMeshAgent,是不是就不会被锁定y轴了呢?

正好,查官方API,有GetComponent<NavMeshAgent>().Stop( true )这个函数让寻路暂停。据此对代码进行修改。

private void Update()
{
if (target != null)
{
agent.SetDestination(target.position);
character.Move(agent.desiredVelocity, false, m_Jump);
}
else
{
character.Move(Vector3.zero, false, m_Jump);
}
m_Jump = false;
}

void OnTriggerEnter(Collider co)
{
if (co.tag == "Jump!")
{
m_Jump = true;
StartCoroutine(Jumping());
}
}
IEnumerator Jumping()
{
agent.Stop(true);

yield return new WaitForSeconds(2f);

agent.Resume();
}
然而角色还是没有跳起来,这说明把NavMeshAgent暂停并不会解除y轴的锁定。

既然暂停没用,那么还有最后一招狠的,把NavMshAgent.enable设置为false,看看能否摆脱y轴的束缚。

IEnumerator Jumping()
{
agent.enabled = false;

yield return new WaitForSeconds(2f);

agent.enabled = true;
}
结果是角色蹦起来了



结论就是,我们可以设置一个起跳触发装置,当角色走到它的时候,把NavMeshAgent.enable置为false,让它失效一阵子,等角色落地了再重新生效寻路。

二:有空间间隔的寻路

我们发现,按照上面的做法只能做到在同一块plane上寻路,若是有两块plane,角色是无法从这一块寻路到另外一块的,那么这个起跳触发装置也就失效了。

那要从一块plane寻路到另一块plane该怎么做?

在Navigation——Bake面板下,我们可以看到如下图



这里有着各种详细地bake参数,其中有一项叫做JumpDistance,它代表着角色在自动寻径时所能跳的距离。这里我们把它置为2,重新bake。效果如下



我们发现,两块plane出现了很多箭头和圆圈,箭头代表方向,而圆圈我们称之为OffMeshLink。

OffMeshLink的作用就是让两个不相接的寻路面之间有一个寻路的路线,使得从一个面可以寻路到另一个面。

这下我们的角色已经可以自动寻路到对面了,当然之间我们肯定要跳跃一下,那是不是意味着我们必须给每个OffMeshLink的起点都设置一个起跳触发点??

根本没必要!比起我们自制的起跳触发点,有一个更好的触发点——那就是OffMeshLink本身!

查查API,GetComponentInChildren<NavMeshAgent>().isOnOffMeshLink就是判断角色是否处于OffMeshLink,ok,根据这个就可以改代码了

private void Update()
{
if (agent.isOnOffMeshLink)
{
OffMeshLinkData link = agent.currentOffMeshLinkData;
transform.LookAt(link.endPos);
m_Jump = true;
StartCoroutine(Jumping());
}
if (target != null)
{
agent.SetDestination(target.position);
character.Move(agent.desiredVelocity, false, m_Jump);
}
else
{
character.Move(Vector3.zero, false, m_Jump);
}
m_Jump = false;
}
好的,大功告成,我们的角色已经在寻路中跳跃了。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: