Navigation相关组件
导航网格(即 Navigation Mesh,缩写为 NavMesh)
是一种数据结构,用于描述游戏世界的可行走表面,并允许在游戏世界中寻找从一个可行走位置到另一个可行走位置的路径。该数据结构是从关卡几何体自动构建或烘焙的。
相关文档
导航网格代理 (NavMesh Agent)
组件可帮助您创建在朝目标移动时能够彼此避开的角色。代理使用导航网格来推断游戏世界,并知道如何避开彼此以及移动的障碍物。
相关文档
网格外链接 (Off-Mesh Link)
组件允许您合并无法使用可行走表面来表示的导航捷径。例如,跳过沟渠或围栏,或在通过门之前打开门,全都可以描述为网格外链接。
相关文档
导航网格障碍物 (NavMesh Obstacle)
组件可用于描述代理在世界中导航时应避开的移动障碍物。由物理系统控制的木桶或板条箱便是障碍物的典型例子。障碍物正在移动时,代理将尽力避开它,但是障碍物一旦变为静止状态,便会在导航网格中雕刻一个孔,从而使代理能够改变自己的路径来绕过它,或者如果静止的障碍物阻挡了路径,则代理可寻找其他不同的路线。
相关文档
构建导航网格
1.选中目标地形,并将Inspector面板中Static状态设置为Nav Static。
2.打开Navigation窗口(Window->AI->Navigation),选择烘焙即可。
参数
Agent Radius
定义代理中心与墙壁或窗台的接近程度。(间隔)
Agent Height
定义代理可以达到的空间有多低。(进坑)
Max Slope
定义代理走上坡道的陡峭程度。(爬坡)
Step Height
定义代理可以踏上的障碍物的高度。(楼梯)
Drop Height
可跳下的高度。
Jump Distance
可以跃过的距离。
Min Region Area
可剔除未连接的小型导航网格区域。表面积小于指定值的导航网格区域将被移除。
Manual Voxel Size
设置可更改烘焙过程的准确度。默认的精度设置为每个代理半径为 3 个体素,即整个代理宽度为 6 个体素。此设置可在精确度和烘焙速度之间实现良好折衷。
体素大小减半将使内存使用量增加 4 倍,构建场景需要的时间也为 4 倍。(通常不会手动修改,但有两种情况可能需要这样做:构建_更小的代理半径_或_更准确的_导航网格。)
Height Mesh
由于导航网格是可行走空间的近似形状,因此在构建导航网格时会使某些特征扁平化。例如,楼梯可能在导航网格中显示为斜坡。如果游戏需要准确放置代理,则应在烘焙导航网格时启用 Height Mesh 构建。(但是会更消耗性能)
代码部分
实现鼠标右击地面移动到目标点。
需要给控制角色挂上NavMesh Agent组件和下面脚本。
NavMeshAgent agent;
void Start()
{
agent = GetComponent<NavMeshAgent>();
}
void Update()
{
if (Input.GetMouseButtonDown(1))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
bool rec = Physics.Raycast(ray,out hitInfo, 100);
if (rec)
{
//设置目标点
agent.SetDestination(hitInfo.point);
//中止
//agent.isStopped = true;
//返回距离,下一帧开始出结果
//无法导航的位置会返回Infinite
Debug.Log(agent.remainingDistance);
}
}
}
在一组点之间巡逻代码。
using UnityEngine;
using UnityEngine.AI;
using System.Collections;
public class Patrol : MonoBehaviour {
public Transform[] points;
private int destPoint = 0;
private NavMeshAgent agent;
void Start () {
agent = GetComponent<NavMeshAgent>();
// 禁用自动制动将允许点之间的
// 连续移动(即,代理在接近目标点时
// 不会减速)。
agent.autoBraking = false;
GotoNextPoint();
}
void GotoNextPoint() {
// 如果未设置任何点,则返回
if (points.Length == 0)
return;
//将代理设置为前往当前选定的目标。
agent.destination = points[destPoint].position;
//选择数组中的下一个点作为目标,
// 如有必要,循环到开始。
destPoint = (destPoint + 1) % points.Length;
}
void Update () {
//当代理接近当前目标点时,
// 选择下一个目标点。
if (!agent.pathPending && agent.remainingDistance < 0.5f)
GotoNextPoint();
}
}
要注意加速度acceleration的设置,因为即使到达目标点也会由于减速效果导致误差。
还有如果存在多个敌人寻路时出现阻塞挤压现象可以通过给敌人增加NavMesh Obstacle组件解决。(将敌人设为障碍物)
补充一些比较重要的知识点
导航区域和成本
每个导航网格代理 (NavMesh Agent) 都有一个_区域遮罩 (Area Mask)_,可用于指定代理可以移动的区域。
比如我们做一个丧尸游戏,丧尸不能通过安全区,我们就可以在安全区区域设置Navigation Areas并在NavMesh Agent设置Area Mask。
关于Cost,其实就是在每单位距离移动的消耗。
比如说有两块区域,第一块是1米Cost为3,第二块是2米Cost为1,那么NavMesh Agent会走第二块。如果第二块变成4米那么就会走第一块。
和其他组件的冲突问题
AI模型不贴地行走问题(浮空)
烘焙地形时勾选HeightMesh即可。