我的游戏开发笔记(六):NavMeshAgent及自动寻径(跳跃)。
2015-09-02 18:43
1266 查看
相信只要用过unity3d4.0以上都都会用过NavMeshAgent这个组件,这是一个十分强大的寻路组件,只要对地形进行bake,然后设置一个目标点,就可以实现高效率的寻路了。
可是unity3d自带的AI用NavMeshAgent寻路,只有跑步走路,若我想跳跃蹲下瞬移怎么办?
在上一篇文章中提到的 Unity手游之路<十>自动寻路Navmesh之跳跃,攀爬,斜坡 虽然很好的实现了这些功能,但是该作者使用的Animation,而我要使用Animator对角色的动作的改变。只能再进一步研究NavMeshAgent了。
一:无空间间隔的寻路
首先,想要角色在自动寻路时进行跳跃,那必须给他个判断条件吧?第一个想到的肯定是设置一个触发开关,当角色寻径到这个地点的时候就把m_Jump设为true就行了。
然后我发现,角色只会执行跳跃这个动作而不会跳起来,如下图(看不出来,反正就是在地上滚了一圈,本来应该是跳起来在天上滚的)
从这里可以推断出,若使用NavMeshAgent来寻路,角色的y轴被锁定在了NavMesh面,也就是bake后从Navigation看到的蓝色的那层,不可改变。
有了这个推断,若用NavMeshAgent自动寻路,y轴会被锁定,反过来说,若不用NavMeshAgent,是不是就不会被锁定y轴了呢?
正好,查官方API,有GetComponent<NavMeshAgent>().Stop( true )这个函数让寻路暂停。据此对代码进行修改。
既然暂停没用,那么还有最后一招狠的,把NavMshAgent.enable设置为false,看看能否摆脱y轴的束缚。
结论就是,我们可以设置一个起跳触发装置,当角色走到它的时候,把NavMeshAgent.enable置为false,让它失效一阵子,等角色落地了再重新生效寻路。
二:有空间间隔的寻路
我们发现,按照上面的做法只能做到在同一块plane上寻路,若是有两块plane,角色是无法从这一块寻路到另外一块的,那么这个起跳触发装置也就失效了。
那要从一块plane寻路到另一块plane该怎么做?
在Navigation——Bake面板下,我们可以看到如下图
这里有着各种详细地bake参数,其中有一项叫做JumpDistance,它代表着角色在自动寻径时所能跳的距离。这里我们把它置为2,重新bake。效果如下
我们发现,两块plane出现了很多箭头和圆圈,箭头代表方向,而圆圈我们称之为OffMeshLink。
OffMeshLink的作用就是让两个不相接的寻路面之间有一个寻路的路线,使得从一个面可以寻路到另一个面。
这下我们的角色已经可以自动寻路到对面了,当然之间我们肯定要跳跃一下,那是不是意味着我们必须给每个OffMeshLink的起点都设置一个起跳触发点??
根本没必要!比起我们自制的起跳触发点,有一个更好的触发点——那就是OffMeshLink本身!
查查API,GetComponentInChildren<NavMeshAgent>().isOnOffMeshLink就是判断角色是否处于OffMeshLink,ok,根据这个就可以改代码了
可是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; }好的,大功告成,我们的角色已经在寻路中跳跃了。
相关文章推荐
- 我的渺小
- js学习
- OC 中#pragma mark [-] xxx
- HTML5离线存储
- OPS - Parrallel Control System
- Node.js最新Web技术栈(2015年5月)
- HDU 4634 Swipe Bo (BFS)
- FZU 2195 检查站点 (树形dp)
- [JavaScript 随笔] 垃圾回收
- 【LeetCode】之Remove Duplicates from Sorted Array
- 运用comparable类对数据对象做排序
- 将搜狗输入法(拼音键盘)作为默认输入键盘
- spark core源码分析11 RDD缓存及checkpoint
- android 按两次返回到桌面
- HDU 4467 Graph
- 分析HTTP请求返回304状态码
- 771 密钥解密【字符串处理】
- 游标
- 深入解析HTML5使用SVG图像时的viewBox属性用法
- iscsi挂载远端磁盘的学习笔记