NavMesh(导航网格)是3D游戏世界中用于实现动态物体自动寻路的一种技术,将游戏中复杂的结构组织关系简化为带有一定信息的网格,在这些网格的基础上通过一系列的计算来实现自动寻路。导航时,只需要给导航物体挂载导航组建,导航物体便会自行根据目标点来寻找最直接的路线,并沿着该线路到达目标点。
1.生成导航网格
选择菜单栏中的Windows - Navigation
打开后会出现以下面板
Navigation面板
1.Object
需要你在场景中选择一个带有网格渲染的游戏对象或者地形
我们在场景中添加一个cube,并点击它。
然后我们把Navigation Static给勾选上
Navigation Static
选择你想要使用的物体,把他们标记为‘导航静态(Navigation static)’这就会告诉Unity这些物体是静态的(非移动),在寻路的时候应该被考虑进去。
这个就是Navigation有关Object这一块,还有Generate OffMeshLinks和Navigation Area后面会讲。
2.Agents
agents也就是我们的导航代理,是个圆柱体。
Name:名字
Radius:半径
Height:高度
Step Height:每一步的高度
Max Slope:可以通过的斜坡的倾斜角,范围在0到60度
3.Areas
我们可以设置一些新的Area,右边那个值我们称为该层的行走代价(Cost),Cost值越大,行走的代价越高。
这个就可以用到,当有两条路径进行选择的时候,我们可以通过设置两个不同Cost的Area,让物体走向指定路径
设置的话在Object的Navigation Area上就可以选择(和inspector窗口的layer以及tag是一个用法)
4.Bake
Bake烘培参数面板
- Radius:导航代理的半径,半径越小生成的网格面积越大。
- Height:导航代理的高度。
- Max Slope:导航代理能够行走的斜坡的最大坡度(最大60度)
- Step Height:导航代理一步能跨越的台阶高度
- Drop Height:地形网格的高度差,低于此值,导航代理可以跳落
- Jump Distance:允许最大的跳跃距离。
单击该面板右下角的Bake按钮,就可以生成导航网格。
eg:
接着我们通过一个案例来简单讲讲使用:
案例1:通过鼠标点击实现移动到目标点
我们先来搭建一个这样的场景,一个Plane,两个蓝色的Cube作为障碍物,红色Cube是通过导航网络移动的物体,还有一个小球作为目标点。
我们先来实现通过导航到达小球位置。
将Plane还有两个障碍物的Navigation Static给勾选上,在点击Bake,就可以生成导航网络
导航网络建好后,我们选择需要寻路的物体,添加Nav MeshAgent组件。
Radius:物体的半径
Speed:物体的行进最大速度
Acceleration:物体的行进加速度
Augular Speed:行进过程中转向时的角速度。
Stopping Distance:离目标距离还有多远时停止。
然后再添加一个脚本Cubenav
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;//NavMeshAgent所需要的命名空间
public class cubenav : MonoBehaviour
{
private NavMeshAgent agent;
public GameObject target;
void Start()
{
agent = GetComponent<NavMeshAgent>();
}
void Update()
{
agent.destination = target.transform.position;
}
}
运行结果:
接着我们再实现鼠标点击的效果
我们改一下代码就行了,这里通过射线的方式实现
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;//NavMeshAgent所需要的命名空间
public class cubenav : MonoBehaviour
{
private NavMeshAgent agent;
public GameObject target;
// Start is called before the first frame update
void Start()
{
agent = GetComponent<NavMeshAgent>();
}
// Update is called once per frame
void Update()
{
//agent.destination = target.transform.position;
if (Input.GetMouseButton(0))
{
Ray ray = UnityEngine.Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit info;
if (Physics.Raycast(ray, out info))//判断射线释放与碰撞器接触
{
if (info.collider.gameObject.tag == "floor")//将plane的tag设置为floor
{
agent.destination = info.point;//RaycastHit类的point会返回射线碰到碰撞器的碰撞点
}
}
}
}
}
运行结果:
OffMeshLinks:分离网格链接
分离网格链接用在不相连的导航区域间创建路径。
使用:
将两个plane的Generate OffMeshLinks勾选上
根据Bake中的这两个参数(如果两个plane满足这个条件),就可以Bake出分离网格链接
这种方式会给出很多路径
如果想要单一路径的话
我们可以创建三个空对象
把start和end的position分别设置为两个平台的指定位置
再在link上添加Off Mesh Link组件,把start和end分别拖拽进来,再重新Bake(如果没反应,有可能是重合了,就调一下Bake中的那两个参数,使这两个平台不满足要求,这样我们看的也清楚一些)
这样就算不勾选上Generate OffMeshLinks,也能生成唯一的分离网格链接