Navigation窗口

        Unity 的导航系统给 3D 场景的 AI 寻路提供了一个相当不错的解决方案。需要导航的对象我们称之为 agent(代理) 。

        我们可以(在编辑环境下)为不同类型的 agent 为烘焙静态的场景,并产生一种名为 NavMesh 的资产。NavMesh 是一种数据结构,描述游戏世界的可行走表面,并允许寻路。

Object页签

该项用于具体对象的烘焙设置,只有选中了游戏物体,并且该物体上有 Mesh Renderers 或是 Terrains 组件的时候才生效

默认该对象是不参与烘焙的,如果我们希望该游戏对象参与烘焙,我们需要勾选 Navgation Static 选项。在勾选该选项后,下面两个设置就可以配置了。

Generate OffMeshLinks 是一个标记属性,勾选后告诉 Unity:在烘焙 NavMesh 时,自动计算并生成可跳跃/可掉落的连接路径

它解决了导航网格的"断裂"问题——当地面不连续时(如沟壑、平台边缘),AI 默认会停在边界。开启此参数后,Unity 会自动创建虚拟的"桥梁",让角色能够:

  • Jump-Across(横向跳跃):跳过沟壑或裂缝

  • Drop-Down(纵向掉落):从高处平台跳落到低处

Bake页签

根据地形空间决定哪些地方可以烘焙——比如Agent Height高1m,则0.9米的桥洞就无法烘焙成寻路地形

下面两个属性,前面介绍 Object 中的那个图是相关的。

  • Drop Height: 能产生 OffMeshLink 的最大高度,并且产生的 OffMeshLink 的类型为 OffMeshLinkType.LinkTypeJumpAcross
  • JumpDistance:能产生 OffMeshLink 的最大距离,并且产生的 OffMeshLink 的类型为 OffMeshLinkType.LinkTypeJumpAcross。另外需要注意的是只有同样高度的平面才能自动生成跳跃的外连接

advanced面板(不太重要,一般不修改)

烘焙后生成了NavMesh文件夹

打开该文件后,是一堆二进制数据

Areas页签

我们通过我们可以将不同的地形表示用不同的区域进行表示,最多可以有 32 种区域。系统内置了 三种区域:Walkable、Not Walkable、 Jump, 除此之外还有 29 中区域可供设置。

area 的成本,Unity 使用 A* 计算最最短路径,两点间的代价为 距离 * 成本

如上图在同样的距离下 Water 的成本是 Walkable 的两倍,那么代理更容易走 Walkable area 而不是 water 。

通过此处设置物体Area

导航网格寻路组件

  • 核心作用:基于烘焙好的导航网格数据,使游戏对象能在场景中自动寻路
  • 工作原理:采用A*寻路算法计算最优路径,实现障碍物规避
  • 数据依赖:需要预先通过导航网格生成组件准备地形可通行数据

NavMeshAgent 组件

        该组件是我们使用导航系统最重要的组件,需要导航的对象必须挂载。该组件可以帮助 AI 寻路,还可以自动的控制 AI 移动。

相关API

知识点三 寻路组件代码相关
// 使用网格相关脚本需要引用命名空间
UnityEngine.AI

#region 常用内容
// 自动寻路设置目标点
agent.SetDestination()

// 停止寻路
agent.isStopped = true;

#region 变量
// 关键变量
// 1. 面板参数相关 速度 加速度 旋转速度等等
print(agent.speed);
print(agent.acceleration);
print(agent.angularSpeed);

// 2. 其它重要属性
// 2-1 当前是否有路径
if (agent.hasPath)
{
    
}

// 2-2 代理目标点 可以设置 也可以得到
print(agent.destination);

// 2-3 是否停止 可以得到也可以设置
print(agent.isStopped);

// 2-4 当前路径
print(agent.path);

// 2-5 路径是否在计算中
if (agent.pathPending)
{
    
}

// 2-6 路径状态
print(agent.pathStatus);

// 2-7 是否更新位置
agent.updatePosition = true;

// 2-8 是否更新角度
agent.updateRotation = true;

点击目标计算

void Update()
{
    // 1. 鼠标左键点击检测
    if( Input.GetMouseButtonDown(0) )
    {
        RaycastHit hit;
        // 2. 从相机向鼠标位置发射射线,检测碰撞
        if( Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit ) )
        {
            print(hit.collider.name);           // 打印被点击物体的名称
            agent.isStopped = false;            // 恢复导航代理移动
            
            // 让对象朝目标点移动:先生成行进路径,然后再移动
            agent.SetDestination(hit.point);    // 设置导航目标点为射线命中点
        }
    }

    // 3. 空格键检测 - 停止移动
    if( Input.GetKeyDown(KeyCode.Space) )
    {
        agent.isStopped = true;                 // 停止导航代理
    }
}

SetDestination() 的底层逻辑是同步计算路径,异步执行移动

网格寻路使用流程

注意取消勾选这个:否则Nav的speed不会生效

1、通过Object页签对物体进行筛选和设置

        比如这里Cube和Plane是地形,需要烘焙,而wp_BoStaff是角色不需要烘焙

2、Bake生成蓝色区域

3、角色挂载脚本如下:

int类型参数过渡条件一般用Equal或者NotEqual进行判断

代码情况如下:

using Spine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class TestNav : MonoBehaviour
{
    private NavMeshAgent agent;
    private Animator animator;


    void Start()
    {
        agent = this.GetComponent<NavMeshAgent>();
        animator = this.GetComponent<Animator>();
    }
    void Update()
    {
        // 1. 鼠标左键点击检测
        if (Input.GetMouseButtonDown(0))
        {
            RaycastHit hit;
            // 2. 从相机发射射线检测场景
            if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit))
            {
                print(hit.collider.name);           // 打印被点击物体的名称
                agent.SetDestination(hit.point);    // 设置导航目标点
            }
        }

        // 3. 根据导航代理速度更新动画状态
        if (agent.velocity == Vector3.zero)
        {
            animator.SetInteger("Speed", 0);
        }
        // 静止 → 播放待机动画
        else
        {
            animator.SetInteger("Speed", 1);        // 移动中 → 播放行走/奔跑动画
            Debug.Log("移动中");
        }
           
    }
}

导航脚本外连接组件

如果直接Bake,Unity会自动生成好很多跳跃双向点,如果只需要自己设置跳跃节点,那么就使用如下组件

Off-MeshLink

Start 描述网格外链接起始位置的对象。
End 描述网格外链接起始位置的对象。
Cost Override 如果值为正,则在计算处理路径请求的路径成本时使用该值。否则,使用默认成本(此游戏对象所属区域的成本)。如果 Cost Override 设置为值 3.0,则在网格外链接上移动的成本将是在默认导航网格区域上移动相同距离的成本的三倍。如果希望让代理通常优先选择步行,但当步行距离明显更长时使用网格外链接,则 Cost Override 设置将变得有用。
Bi-Directional 如果启用此属性,则可以在两边都遍历链接。否则,只能按照从 Start 到 End 的方向遍历链接。
Activated 指定寻路器 (pathfinder) 是否将使用此链接(如果将此属性设置为 false,则将忽略它)。
Auto Update Positions 如果启用此属性,当端点移动时,网格外链接将重新连接到导航网格。如果禁用,即使移动了端点,链接也将保持在其起始位置。
Navigation Area 描述链接的导航区域类型。该区域类型允许您对相似区域类型应用常见的遍历成本,并防止某些角色根据代理的区域遮罩 (Area Mask) 访问网格外链接。

在场景中创建两个空节点,然后在OffMeshLink组件中挂载

导航网格动态障碍组件Nav Mesh Obstacle

        当障碍物正在移动时,导航网格代理会尽力避开它。当障碍物静止时,它会在导航网格中雕刻一个孔。导航网格代理随后将改变它们的路径以绕过障碍物,或者如果障碍物导致路径被完全阻挡,则寻找其他不同路线。

Shape 障碍物几何体的形状。选择最适合对象形状的选项。
    Box
        Center 盒体的中心(相对于变换位置)。
        Size 盒体的大小。
    Capsule
        Center 胶囊体的中心(相对于变换位置)。
        Radius 胶囊体的半径。
        Height 胶囊体的高度。
Carve 勾选 Carve 复选框后,导航网格障碍物会在导航网格中创建一个孔(与障碍物shape网格形状有关)
    Move Threshold 当导航网格障碍物的移动距离超过 Move Threshold 设置的值时,Unity 会将其视为移动状态。使用此属性可设置该阈值距离来更新移动的雕孔。
    Time To Stationary 将障碍物视为静止状态所需等候的时间(以秒为单位)。
    Carve Only Stationary 启用此属性后,只有在静止状态时才会雕刻障碍物。请参阅下面的移动的导航网格障碍物的逻辑以了解更多信息

什么时候使用Curve?

        可以频繁消失的障碍物,就不用Curve

        如果固定的障碍,就使用Curve

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐