【Unity】Navigation 选择性寻路:Area Mask


前言

上一章节 我们讲了窄桥、隧道、斜坡、台阶、坠落、跳跃等不同的烘焙方式,但还有一些导航的特殊情况。有时候某些特殊地形只能特定的角色才能通过,比如会游泳的角色才能下水,或者只有猴子才能爬上高坡,这时候就要进行选择性寻路了,通常我们使用Area Mask来实现这个功能。

Area Mask 区域遮罩

Area Mask 用于将路面进行分层,我们可以给物体外链设置不同的遮罩区域,再给不同的角色设定不同的可移动区域。这样各种角色就有了自己的寻路方式。

下面我们针对上台阶和爬梯子两种情况对角色做区分,让一种角色只能爬梯子,让另一种角色只能上台阶。

首先我们要选中 Navigation 中的 Areas 标签页,添加两种区域:Step 上台阶、Climb 攀爬。
在这里插入图片描述
注意:区域名称后面的数值(移动消耗 cost)代表该区域的移动力消耗。有些游戏中角色在不同的区域移动时速度会受到影响,比如森林、沙地、浅滩等,此时通过设置不同的移动消耗值就可以实现绕过行动困难的区域。

物体选择性寻路(上台阶)

先选中台阶的三个物体,然后进入 Navigation 中的 Object 选项卡,将 Navigation Area 选为 Step。
在这里插入图片描述

烘焙结果如下:
在这里插入图片描述
我们看到台阶的部分已经烘焙成粉色了。

然后再将可以上台阶的角色的 Area Mask 属性中的 Step 选中,如下图:
在这里插入图片描述
此时我们的角色就可以在台阶上移动了。

外链选择性寻路(爬梯子)

先选中外链的空物体,将 Navigation Area 属性设置为 Climb ,如下图:
在这里插入图片描述

然后再将可以爬梯子角色的 Area Mask 属性中的 Step 选中,如下图:
在这里插入图片描述

最后烘焙一下导航路径,我们的功能就完成了,看看效果吧。
在这里插入图片描述

代码动态控制移动区域

首先我们要了解的是,AreaMask 是一个多选框,角色可以同时选择多个可移动区域,所以 Unity 将 AreaMask 设计成了一个数字,每个 Area 代表的都是 2 的 n 次方,将选中层的数字相加后的结果就是 AreaMask 最后的值。例如,我同时选择 Walkable、Jump、Climb 三个区域,那么最后得到的值就是 1 + 4 + 16 = 21,当系统接收到 21 这个数字,就知道我们选择了这三个区域。
在这里插入图片描述
操作代码如下:

using UnityEngine;
using UnityEngine.AI;

namespace TDGameDemo.Nav
{
    /// <summary>
    /// 导航测试类
    /// </summary>
    public class NavTest : MonoBehaviour
    {
        private NavMeshAgent agent;
        public Transform target;

        public int areaNum;

        private void Start()
        {
            agent = GetComponent<NavMeshAgent>();
        }

        private void LateUpdate()
        {
        	bool flag = agent.SetDestination(target.position);
        	
        	// 当按下空格时改变移动区域
            if (Input.GetKeyDown(KeyCode.Space))
            {
                agent.areaMask = areaNum;
            }
        }
    }
}

我们让之前爬梯子的角色现在去走台阶:将对象 NavTest 组件的 AreaNum 设置为15(Step + Jump + Not Walkable + Walkable)。
在这里插入图片描述

让之前走台阶的角色现在只能走普通路面:将对象 NavTest 组件的 AreaNum 设置为1(Walkable)。
在这里插入图片描述

在运行开始时按下空格,给角色重新指定移动区域,使角色重新选择路线。看看效果吧。
在这里插入图片描述

停止和继续

有时候我们也需要角色停止导航,这时可以调用 NavMeshAgent 中的 Stop 和 Resume 方法。


更多内容请查看总目录【Unity】Unity学习笔记目录整理

<think>好的,我现在需要帮助用户解决关于在Unity中通过烘焙实现寻路功能的问题。首先,我需要仔细理解用户的需求。用户提到了“烘焙”和“寻路”,结合提供的引用内容,看起来他们想了解如何利用UnityNavigation系统进行动态烘焙和导航设置。 接下来,我应该回顾用户提供的引用内容,特别是引用[1]、[4]、[5]中的信息,因为这些直接提到了动态烘焙和寻路组件的使用。用户可能希望得到一个步骤式的教程,涵盖场景准备、静态设置、参数配置、动态烘焙脚本以及最终效果测试。需要确保回答符合用户的要求,即结构清晰、真实可靠,并且正确使用LaTeX格式。 首先,步骤一应该是场景准备,设置地面和障碍物,并将它们标记为静态,这样才能进行烘焙。引用[5]中提到将Plane和Wall设置为静态,这很关键,因为Navigation系统依赖静态物体来生成可行走区域。 然后,步骤二涉及Navigation窗口的参数配置,如Agent的半径、高度、坡度等。引用[4]详细说明了这些参数的作用,比如Agent Radius和Max Slope,这些参数影响AI代理的移动能力,需要正确设置以确保导航网格正确生成。 接下来是步骤三,烘焙导航网格。这里需要指导用户如何使用Bake按钮生成导航网格,并解释生成的蓝色区域代表可行走区域。引用[5]中的步骤3提到了这一点,用户需要明确如何操作。 步骤四可能涉及动态烘焙的实现,即如何在运行时动态生成和更新导航网格。引用[1]提到了动态烘焙的脚本,需要挂载到人物和地板上,通过范围检测来动态更新烘焙区域。这部分需要详细说明脚本的作用和如何设置触发范围,确保人物移动时周围的区域被正确烘焙。 然后是步骤五,应用NavMeshAgent组件,让角色能够自动寻路。需要引用[2]中的信息,说明如何添加组件并设置目标点,使用SetDestination方法实现移动。此外,可能需要提到OffMeshLink来处理跨越障碍的情况,如引用[3]中提到的添加隐藏平面连接不连续区域。 最后,步骤六是测试和优化,强调调整参数和动态烘焙范围的重要性,引用[1]中的示例说明如何根据需求调整范围大小。 在回答过程中,需要确保所有数学表达式或代码示例使用正确的格式,比如行内公式用$...$,独立公式用$$...$$。同时,生成的相关问题需要围绕用户可能进一步关心的点,如动态烘焙原理、性能优化、常见问题等,这有助于用户深入学习和解决问题。 需要检查是否有遗漏的步骤或关键点,例如是否提到AreaMask的使用,或者如何处理动态生成的障碍物。引用[4]中的Areas部分可以补充说明如何通过AreaMask屏蔽特定区域,增强寻路的灵活性。 另外,用户提供的引用中有提到动态生成地图和动态烘焙地形,这可能涉及到运行时修改导航网格,需要确保脚本部分正确实现这一功能,如引用[1]中的两个脚本协作。需要详细解释每个脚本的作用,比如一个挂在人物身上用于检测范围,另一个挂在地板上处理烘焙。 最后,确保回答结构清晰,分步骤说明,每个步骤都有对应的引用支持,并且自然地在段落末尾添加引用标识。避免使用复杂的术语,保持语言简洁易懂,适合不同层次的用户理解。</think>以下是在Unity中通过烘焙实现寻路功能的详细教程,结合Navigation系统和动态烘焙技术: ### 一、基础环境搭建 1. **场景准备** - 创建3D Object中的Plane作为地面 - 添加Cube作为障碍物(如墙壁) - 设置障碍物和地面为静态:选中物体后勾选Inspector面板右上角的`Static`[^5] 2. **配置导航参数** 打开`Window > AI > Navigation`窗口: - **Agent参数**: - Agent Radius:$r=0.5m$(角色半径) - Max Slope:$\theta_{max}=45^\circ$(最大可行走坡度) - Step Height:$h_{step}=0.3m$(可跨越高度)[^4] ### 二、静态烘焙流程 ```csharp // 烘焙指令触发代码(编辑器模式) NavMeshBuilder.BuildNavMesh(); ``` 1. 在Navigation窗口选择`Bake`标签 2. 点击`Bake`按钮生成导航网格 3. 生成结果:场景中蓝色区域表示可行走路径[^5] ### 三、动态烘焙实现 需配合两个脚本实现动态范围烘焙: 1. **角色移动检测脚本**(挂载在角色上) ```csharp public class DynamicBaker : MonoBehaviour { public float bakeRadius = 5f; // 烘焙范围半径 void Update() { NavMeshBuilder.UpdateNavMeshData( navMeshData, buildSettings, new Bounds(transform.position, Vector3.one * bakeRadius), // 动态范围 transform.localToWorldMatrix ); } } ``` 该脚本会使角色周围$R=5m$圆形范围实时更新导航网格[^1] 2. **地面响应脚本**(挂载在地板预制体上) ```csharp public class NavMeshUpdater : MonoBehaviour { void OnCollisionEnter(Collision col) { if(col.gameObject.CompareTag("Player")) { BakeLocalArea(col.contacts[0].point); } } } ``` ### 四、导航应用 1. 给角色添加`NavMeshAgent`组件 2. 设置目标点实现自动寻路: ```csharp NavMeshAgent agent = GetComponent<NavMeshAgent>(); agent.SetDestination(targetPosition); // 目标坐标设置[^2] ``` ### 五、特殊地形处理 对于不连续地形(如沟壑): 1. 在缺口处添加隐藏平面 2. 设置该平面为`Navigation Static` 3. 烘焙后隐藏物体[^3] $$ \text{可行走区域} = \bigcup_{i=1}^{n} S_i - \sum_{j=1}^{m} O_j $$ 其中$S_i$为可行走表面,$O_j$为障碍物体积 ### 六、效果验证 完成后的特征: - 角色移动时地面实时生成导航网格 - 自动绕过障碍物选择最短路径 - 可跨越高度$h \leq 0.3m$的台阶[^4]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值