Unity Navigation Mesh 自动寻路
利用Unity自带的导航网格寻路,Unity2022.1.2f1c1
(1)创建地形
利用最基础的 Cube 模型搭建的一个简单的场景
在 Hierarchy 面板下
(1.1)可走的路:可以正常行走、通行的地方:如 地面、台阶、斜坡、平台 等
Road 下面的物体是搭建的可走的路,包括地面、左下方的台阶、左上方一个悬空的台,右上方一个带斜坡的台
(1.2)障碍物:不能走、不能通过的地方:如墙、门、较大的物体
Obstacle 下面的红色墙
障碍物需要添加组件:NavMeshObstacle、Rigidbody
NavMeshObstacle 勾选 Carve
(1.3)连接点:从一个点可以走、跳跃 到达另一个点,如图中 上方两个平台都是悬空的,且两个平台之间有一定的距离,如果想让人从一个台阶上跳跃到另一个台阶上,可以分别在两个平台上建立两个连接点。
Line 下面的连接点, start 和 to 是一组,from 和 end 是一组
在一个物体上添加组件:OffMeshLink
将需要连接的两个点分别拖拽到 OffMeshLink 组件的 Start、End 上
(2) 设置面板
菜单栏:Window->AI-Navigation 打开设置面板
(2.1) Agents 设置
Radius:人的半径
Height:人的高度
Step Height: 人一步漫出的高度,上台阶的高度
Max Slope:人可以行走的斜坡的最大角度
(2.2) Object 设置
全选:路、连接点、障碍物
显示已选择了 13 个物体
勾选 Navigation Static
Generate OffMeshLinks 自动生成连接点,此处先不勾选,后边再说
设置完成然后到 Bake
(2.3) Bake 设置
各种参数想了解的自己查文档就行了
点击
Bake 按钮
查看烘焙结果
在 Scene 视图下看到的效果如下图( 可以跟上边第一张烘焙之前的图对比下)
场景被划分成了很多凸多边形的连接
蓝色部分就是可行走的路
白色部分是不可行走的地方
还有四个圈,两两之间有一个双向箭头连接着,这就是两组连接点,人可以从一个连接点跳跃到另一个连接点
(2.4)导航网格烘焙后不想要了如何撤销?
在 Back 面板点击 下方的
Clear 按钮
即可清除烘焙好的导航网页
(3)Object -> Generate OffMeshLinks 回到 Object 设置面板
全选:路、连接点、障碍物
勾选 Navigation Static
勾选 Generate OffMeshLinks
(3.1) 到 Bake 面板
设置 Generated Off Mesh Links
Drop Height:人在两个连接点之间 上下跳的最大高度 单位米
Jump Distance:人在两个连接点之间 跳跃的最大距离 单位米
点击
Bake 按钮
,看效果
多了很多组连接点,这是烘焙路径时根据台阶、平台、路面之间的高度以及距离自动生成了很多连接点
(4) 因为自动生成的连接点很多不是我们想要的,我们想自己控制在哪里添加连接点,所以我们不用自动生成的连接点,将烘焙好的导航网格
Clear
掉,删除掉 Generated Off Mesh Links 设置,重新
Back
(5)导航网格生成好了,如何使用?
创建一个圆柱体Cylinder就是我们的角色了
添加组件:NavMeshAgent
各种参数可查文档
添加移动控制脚本 MoveController.cs 添加到 角色圆柱体Cylinder 上
引用命名空间
using UnityEngine.AI;
using UnityEngine;
using UnityEngine.AI;
public class MoveController : MonoBehaviour
{
private NavMeshAgent _navMeshAgent;
GameObject go;
void Start()
{
_navMeshAgent = GetComponent<NavMeshAgent>();
_navMeshAgent.speed = 3.5f;
go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
go.transform.localScale = Vector3.one * 0.3f;
go.GetComponent<MeshRenderer>().material.color = Color.red;
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
FindPoint();
}
}
private void FindPoint()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
//发射射线,如果射线碰撞到带有 Collider 组件的对象将返回 true,否则返回 false
if (Physics.Raycast(ray, out hitInfo))
{
// hitInfo.point 为射线和球面碰撞点坐标(鼠标点击球面坐标)
SetDestination(hitInfo.point);
go.transform.position = hitInfo.point;
}
}
private void SetDestination(Vector3 destination)
{
_navMeshAgent.destination = destination;
}
}
运行Unity 通过鼠标点击,获取到一个位置,让人移动到点击位置