简介
导航区域(Area)定义了移动穿过特定区域的难度,在路径查找过程中将优先选择 成本(Cost)较低的区域。此外,每个 AI 代理(AI Agent)都有一个 区域遮罩(Area Mask),可用于指定 AI 代理可以移动的区域。
区域作用
区域类型常用于以下两种情况:
- 为不同的区域设置不同的成本,比如过河会优先选择桥,如果目标在水中也能进入水域。
【NavMesh_Areas001.mp4】
- 使用区域遮罩让部分区域只能让特定角色进入,比如鱼只能在水中游泳而不能像人物一样上岸。
【NavMesh_Areas002.mp4】
用于烘焙导航网格的每个 游戏对象(Game Object)都可以单选后在导航网格窗口设置其区域类型,此外,每个 网格连接(OffMeshLink)组件(Component)都有一个 区域(Area)属性来指定该网格连接的区域类型。
区域类型
您可以在 导航网格窗口(NavMesh Window)的 烘焙区域(Baked Area)选项条目中设置区域类型。关于导航网格窗口的启动方法请参阅 导航网格窗口 章节。
【NavMesh_Areas003.png】
您可以设置 13 种自定义类型和 3 种内置类型:可步行(Walkable)、不可步行(Not Walkable)和 跳跃(Jump)。
- 可步行(Walkable)是一种通用区域类型,指定该区域可以步行。
- 不可步行(Not Walkable)是一种阻止导航寻路的通用区域类型。当您想要将某个 游戏对象(Game Object)标记为障碍物,但又不想将 NavMesh 置于其之上时使用。
- 跳跃(Jump)是每个 网格连接(OffMeshLink)组件(Component)区域(Area)属性的默认值。
如果不同区域类型的多个游戏对象重叠,则生成的导航网格区域类型通常是索引最高的一种。但 不可步行(Not Walkable)类型始终优先于其他区域类型。
寻路成本
寻路成本(Pathfinding Cost)为您控制 AI 代理(AI Agent)在寻找路径时偏爱哪些区域。您可以在 导航网格窗口(NavMesh Window)的 烘焙区域(Baked Area)选项条目中设置不同类型区域的寻路成本。
【NavMesh_Areas004.png】
在不设置寻路成本的情况下, AI 代理会选择前往目标点的最短路径,您可以在 导航网格窗口(NavMesh Window)的 烘焙区域(Baked Area)选项条目中设置每种区域类型的成本。该成本的数值代表 AI 代理在计算最优路径时,计算通过该类型的区域的路程为实际通行该区域路程的多少倍。
| -------------- 例如,图中水面对象区域的寻路成本设置为 3.0,则穿越该区域的路程将被视为是替代路线的三倍。 【NavMesh_Areas005.png】 走水面三倍的距离肯定要比绕路长的,因此 AI 代理会直接绕过水面走到目标地点。 【NavMesh_Areas006.gif】 但是如果绕路的距离大于三倍直接走水面的距离,AI 代理会选择直接进入水面走到目的地。 【NavMesh_Areas007.gif】 -------------- |
区域遮罩
每个代理都可以选择其 区域遮罩(Area Mask),区域遮罩用于判断 AI 代理(AI Agent)在导航时可以进入或经过哪些区域。
您可以在 网格寻路代理(NavMeshAgent)组件(Component)的 区域遮罩(Area Mask)属性中多选该代理可以进入或经过的区域。
【NavMesh_Areas008.png】
您也可以在 NavMeshAgent 类中调用 NavMeshAgent.areaMask(AreaID) 动态设置该代理的区域遮罩信息。详情请参阅 API 文档关于 NavMeshAgent.areaMask(AreaID) 的内容。
值得注意的是,AreaID 需要用二进制表示,如果代理能通过的区域不止一个,需要用 或(“|”)运算符间隔开两个 AreaID。比如代理的路径可以经过 Walkable 和 Water 区域,导航网格窗口中 烘焙区域(Baked Area)选项条目中设置如下:
【NavMesh_Areas009.png】
脚本如下:
class AgentAreaMask extends Component {
//定义私有变量保存 网格寻路代理(Nav Mesh Agent);
private _aiAgent:NavMeshAgent;
/*
编辑运行时事件;
*/
OnStart(): void {
//获取 网格寻路代理(Nav Mesh Agent)并将其保存为 _aiAgent 私有变量;
this._aiAgent = this.gameObject.GetComponent(NavMeshAgent);
//根据 Walkable 的 AreaID 是 0,将二进制中的 1(True)推进 0 位并保存在变量中;
let AreaWalkable:number = 1 << 0;
//根据 Water 的 AreaID 是 3,将二进制中的 1(True)推进 3 位并保存在变量中;
let AreaWater:number = 1 << 3;
//设置代理的区域遮罩为仅能通过 Walkable 和 Water 区域;
this._aiAgent.areaMask = AreaWalkable | AreaWater;
}
OnUpdate(): void {
}
}