Unity3D学习(15)之Navmesh使用

来源:互联网 发布:巨人网络 2017财报 编辑:程序博客网 时间:2024/06/03 22:47

最近学了Unity3D的自带寻路Navmesh,觉得挺好用的,所以写出来和大家分享一下。

自带寻路Navmesh的三大组件:

1.Nav Mesh Agent:主要挂在寻路物体上

2.Off Mesh Link:实现区域转移功能(例如,有时不一定只是在地面上进行寻路,可能有些高高的平台,平台与地面是不相连的,使用该组件可以跳到平台上)

3.Nav Mesh Obstacle:主要挂在障碍物上

通过Navmesh可以实现自动寻路,爬楼梯,跳跃等功能。先上个效果图。

下面讲一下制作流程

首先从官网下载士兵模型,然后如下添加NavmeshAgent组件,无需加刚体(而且感觉加了刚体会出现鬼畜的现象,但是有时又正常),无需调整

然后建立一个Plane,在Navgation界面如下设置,然后Bake

上网下载桥的3D模型然后做几个Cube形成高低楼层,如上Bake。

为主角添加TestBake.cs脚本让主角走到鼠标点击的点

public class TestBake : MonoBehaviour {    private NavMeshAgent agent;    private Animator animation1;    void Start()    {        //获取组件          agent = GetComponent<NavMeshAgent>();        animation1 = GetComponent<Animator>();    }    void Update()    {        if(Bridge.Open == false)//吊桥相关后面解释        {            agent.areaMask = -1;        }        else        {            agent.areaMask = 1;        }        //鼠标左键点击          if (Input.GetMouseButtonDown(0))        {            //摄像机到点击位置的的射线              Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);            RaycastHit hit;            if (Physics.Raycast(ray, out hit))            {                Debug.Log(hit.collider.name);                //判断点击的是否地形                /*                if (!hit.collider.name.Equals("Plane"))                {                    return;                }                */                //点击位置坐标                  Vector3 point = hit.point;                Debug.Log(point);                //转向                  transform.LookAt(new Vector3(point.x, point.y, point.z));                //设置寻路的目标点                  agent.SetDestination(point);            }        }        //播放动画,判断是否到达了目的地,播放空闲或者跑步动画          if (agent.remainingDistance < 0.5f)        {            animation1.Play("idle");        }        else        {            animation1.Play("run");        }    }}

这时人物已经可以随着你的鼠标点击点自动寻路了

但是你会发现人物不会爬楼梯,你需要为楼梯添加如下组件Off Mesh Link,新建两个点作为起点终点,这里我用两个小正方体做演示,实际游戏应该使用空物体,Bake一下会出现下图的路径。

如果想要实现向上跳,需要像上楼梯一样操作添加

向下跳就简单一点,为物体如下设置即可,Unity会自动帮你计算可以下跳的地方及路线,但是中间有间隔的不会有下跳的路线(如下图的绿色和黄色块之间,只能通过Off Mesh Link实现(上面的方法))

但是我们可以设置下跳的高度以及跳跃的水平距离

然后设置一下多路导航路线,加入Red,Blue,Green,Bridge层,如下设置

建立其他Plane作为路线,在Navigation里面设置相应的层如下(以蓝色层为例)

然后建立三个小兵,颜色为蓝,绿,红。设置如下(以红色为例)

然后添加Solider.cs //其实大致和TestBake差不多只是Solider没有动画而且多了delta为了防止和士兵碰撞

public class Solider : MonoBehaviour{    public float delta = 0.5f;    private NavMeshAgent agent;    // Use this for initialization    void Start()    {        //获取组件          agent = GetComponent<NavMeshAgent>();    }    // Update is called once per frame    void Update()    {        //鼠标左键点击          if (Input.GetMouseButtonDown(0))        {            //摄像机到点击位置的的射线              Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);            RaycastHit hit;            if (Physics.Raycast(ray, out hit))            {                Debug.Log(hit.collider.name);                //判断点击的是否地形                /*                if (!hit.collider.name.Equals("Plane"))                {                    return;                }                */                //点击位置坐标                  Vector3 point = hit.point;                Debug.Log(point);                //转向                  transform.LookAt(new Vector3(point.x, point.y, point.z));                //设置寻路的目标点                  point.x += delta;                point.z += delta;                agent.SetDestination(point);            }        }    }}
然后设置一下吊桥开关与人物行走,建立一个空物体放在吊桥的一端,然后将吊桥拖为空物体的子物体,旋转的时候就是以桥的一端为旋转点,而不是将桥的中心为旋转中心
添加Bridge.cs
public class Bridge : MonoBehaviour {    public static bool Open = false;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {        if(Input.GetKeyDown(KeyCode.Space))//检测空格键按下        Open = !Open;//切换吊桥状态        if(Open == true)        {            this.transform.rotation = Quaternion.Euler(0, 0, 30);//吊起吊桥        }        else if(Open == false)        {            this.transform.rotation = Quaternion.Euler(0, 0, 0);//下降吊桥        }}}
将其层设置为Bridge层并且Bake,然后在testBake里面检测吊桥状态
if(Bridge.Open == false)        {            agent.areaMask = -1;//所有层均可通过        }        else        {            agent.areaMask = 1;//只通过行走层        }
至于为什么是1或者是-1可以参考下面的参考资料,我的博客也是学习了他的博客后写的,这是传送门
如果有兴趣的同学可以去我的Github看一下Homework9
这是我目前的知识水平,可能有一些讲的不够准确欢迎指正,还有看了下贴吧,好像Unity3D自带的NavMesh实用性不大,特别对于大项目来讲,所以一般都会自己编写NavMesh提高效率

1 0
原创粉丝点击