关于 unity-ai-navigation
为 Unity 开发者整理 Unity 6 AI 导航与推理文档的技能指南,涵盖 NavMesh 配置、寻路、动态障碍和 ONNX 模型推理。
主要功能
- 01NavMesh 构建与烘焙
- 02Agent 寻路与移动
- 03动态障碍管理
- 04Off-Mesh Link 配置
- 05Sentis ONNX 推理
适用场景
- 01配置运行时或编辑时 NavMesh
- 02实现角色寻路与路径状态检查
- 03处理动态障碍及跨区域移动
- 04在 Unity 中运行 ONNX 模型
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ nice-wolf-studio/ unity-claude-skills --skill unity-ai-navigation安装后在 Claude Code 中输入/unity-ai-navigation确认已加载。
附带文件references/navmesh-guide.mdreferences/sentis-ml.md
详细介绍
Unity 6 AI 和导航指南
来源:Unity 6.3 LTS 文档(6000.3)
AI 导航概述
软件包: com.unity.ai.navigation(适用于 Unity 6000.3 的 v2.0.11)
AI Navigation 软件包是一套高级组件系统,可实现基于 NavMesh 的导航和寻路。它支持运行时和编辑时构建 NavMesh、动态障碍物管理,以及用于特殊动作(跳跃、开门)的连接系统。
核心组件
| 组件 | 用途 |
|---|---|
| NavMeshSurface | 为特定 Agent 类型定义并构建 NavMesh |
| NavMeshAgent | 角色寻路和移动 |
| NavMeshObstacle | 动态障碍物规避 |
| NavMeshModifier | 根据 Transform 层级影响 NavMesh 生成 |
| NavMeshModifierVolume | 根据体积影响 NavMesh 生成 |
| NavMeshLink | 连接相同或不同的 NavMesh 表面 |
NavMesh 设置
烘焙 NavMesh
- 向 GameObject 添加 NavMeshSurface 组件
- 配置 Agent Type(决定哪些 Agent 可以使用此表面)
- 将 Use Geometry 设置为 Render Meshes 或 Physics Colliders
- 配置 Collect Objects 模式(All、Volume、Current Hierarchy、仅 NavMeshModifier)
- 点击 Bake,或在运行时调用
BuildNavMesh()
NavMeshSurface 属性
| 属性 | 描述 |
|---|---|
| Agent Type | 哪种 NavMesh Agent 配置可以使用此表面 |
| Default Area | Walkable(默认)、Not Walkable、Jump,以及 29 种自定义类型 |
| Use Geometry | Render Meshes 或 Physics Colliders(使用碰撞体可让导航更靠近边缘) |
| Generate Links | 烘焙时自动创建已收集 GameObject 之间的连接 |
| Collect Objects | 所有 GameObject、Volume、Current Hierarchy、仅 NavMeshModifier |
| Include Layers | 按图层筛选 GameObject(默认:Everything) |
高级烘焙参数
| 参数 | 描述 |
|---|---|
| Override Voxel Size | 精度(默认:每个 Agent 半径 3 个体素) |
| Override Tile Size | 瓦片尺寸(默认:256 个体素);尺寸越小,挖空效果越好 |
| Minimum Region Area | 移除小于阈值的断开网格片段 |
| Build Height Mesh | 生成用于角色定位的高度数据 |
烘焙时,系统会排除带有 NavMeshAgent 或 NavMeshObstacle 的 GameObject。
运行时烘焙 NavMesh
using UnityEngine;
using Unity.AI.Navigation;
public class RuntimeNavMeshBaker : MonoBehaviour
{
NavMeshSurface surface;
void Start()
{
surface = GetComponent<NavMeshSurface>();
surface.BuildNavMesh();
}
public void RebakeNavMesh()
{
surface.UpdateNavMesh(surface.navMeshData);
}
}
NavMeshAgent
NavMeshAgent 组件负责寻路和移动控制。
通过以下路径添加:Add Component > Navigation > NavMesh Agent
基本移动
using UnityEngine;
using UnityEngine.AI;
public class MoveTo : MonoBehaviour
{
public Transform goal;
void Start()
{
NavMeshAgent agent = GetComponent<NavMeshAgent>();
agent.destination = goal.position;
}
}
Agent 属性
转向: Speed、Angular Speed、Acceleration、Stopping Distance、Auto Braking
障碍物规避: Radius、Height、Quality(从 None 到 High)、Priority(0-99;数值越低,优先级越高)
Agent 会避开优先级更高的 Agent,并忽略优先级更低的 Agent。
寻路: Auto Traverse OffMesh Link、Auto Repath、Area Mask
Agent 脚本模式
using UnityEngine;
using UnityEngine.AI;
public class AIController : MonoBehaviour
{
NavMeshAgent agent;
void Start() { agent = GetComponent<NavMeshAgent>(); }
public void MoveToTarget(Vector3 target) { agent.SetDestination(target); }
bool HasReachedDestination()
{
if (!agent.pathPending
&& agent.remainingDistance <= agent.stoppingDistance
&& (!agent.hasPath || agent.velocity.sqrMagnitude == 0f))
return true;
return false;
}
public void StopMoving() { agent.isStopped = true; }
public void ResumeMoving() { agent.isStopped = false; }
public void WarpTo(Vector3 position) { agent.Warp(position); }
}
部分路径
如果无法到达目标位置,Agent 会生成一条通往最近可到达位置的部分路径:
if (agent.pathStatus == NavMeshPathStatus.PathPartial)
Debug.Log("Destination unreachable, using partial path");
else if (agent.pathStatus == NavMeshPathStatus.PathInvalid)
Debug.Log("No valid path found");
NavMeshObstacle
定义 Agent 会避开的动态障碍物。通过以下路径添加:Add Component > Navigation > NavMesh Obstacle
形状: Box(Center + Size)或 Capsule(Center + Radius + Height)
挖空
| 属性 | 描述 |
|---|---|
| Move Threshold | 触发移动障碍物更新的距离 |
| Time To Stationary | 被判定为静止前等待的秒数 |
| Carve Only Stationary | 仅在停止移动时挖空 |
- 挖空: 动态修改 NavMesh 拓扑结构(木桶、箱子、门)
- 不挖空: 不修改网格的排除区域(移动中的角色)
using UnityEngine;
using UnityEngine.AI;
public class DynamicObstacle : MonoBehaviour
{
NavMeshObstacle obstacle;
void Start()
{
obstacle = GetComponent<NavMeshObstacle>();
obstacle.carving = true;
obstacle.carveOnlyStationary = true;
}
public void SetBlocking(bool blocking) { obstacle.enabled = blocking; }
}
离网连接(NavMeshLink)
连接分离的 NavMesh 表面。可用于门、跳跃点、边缘和梯子。
通过以下方式添加:GameObject > AI > NavMesh Link 或 Add Component > Navigation > NavMesh Link
| 属性 | 描述 |
|---|---|
| Agent Type | 可通过连接的 Agent 类型 |
| Start/End Transform | 位于连接边缘的 GameObject |
| Width | 连接跨度宽度 |
| Bidirectional | 双向通行 |
| Area Type | 可行走、不可行走或跳跃 |
| Activated | 控制连接是否可用 |
自定义连接遍历
using UnityEngine;
using UnityEngine.AI;
using System.Collections;
public class CustomLinkTraversal : MonoBehaviour
{
NavMeshAgent agent;
void Start()
{
agent = GetComponent<NavMeshAgent>();
agent.autoTraverseOffMeshLink = false;
}
void Update()
{
if (agent.isOnOffMeshLink) StartCoroutine(TraverseLink());
}
IEnumerator TraverseLink()
{
OffMeshLinkData linkData = agent.currentOffMeshLinkData;
Vector3 startPos = agent.transform.position;
Vector3 endPos = linkData.endPos + Vector3.up * agent.baseOffset;
float elapsed = 0f, duration = 0.5f;
while (elapsed < duration)
{
float t = elapsed / duration;
agent.transform.position = Vector3.Lerp(startPos, endPos, t)
+ Vector3.up * Mathf.Sin(t * Mathf.PI) * 2f;
elapsed += Time.deltaTime;
yield return null;
}
agent.CompleteOffMeshLink();
}
}
Unity Sentis 概览
Package: com.unity.sentis(v2.1)——现已更名为 Inference Engine(com.unity.ai.inference)
用于运行 ONNX 模型(opset 7-15)的神经网络推理库,可在所有 Unity 平台上使用 GPU/CPU。
核心工作流
using UnityEngine;
using Unity.Sentis;
public class MLInference : MonoBehaviour
{
public ModelAsset modelAsset;
Model runtimeModel;
Worker worker;
void Start()
{
runtimeModel = ModelLoader.Load(modelAsset);
worker = new Worker(runtimeModel, BackendType.GPUCompute);
}
void RunInference()
{
Tensor<float> input = TextureConverter.ToTensor(
Resources.Load("image") as Texture2D);
worker.Schedule(input);
Tensor<float> output = worker.PeekOutput() as Tensor<float>;
input.Dispose();
}
void OnDestroy() { worker?.Dispose(); }
}
后端类型
| 后端 | 性能 | 说明 |
|---|---|---|
| GPUCompute | 最快(GPU) | 检查 SystemInfo.supportsComputeShaders |
| CPU | 最快(CPU) | 在 WebGL 上较慢(Burst 编译为 WASM) |
| GPUPixel | 较慢 | 无计算着色器时的回退方案 |
完整 API 详情请参阅 skills/unity-ai-navigation/references/sentis-ml.md。
常见 AI 模式
简单状态机
using UnityEngine;
using UnityEngine.AI;
public enum AIState { Idle, Patrol, Chase, Attack }
public class AIStateMachine : MonoBehaviour
{
public AIState currentState = AIState.Idle;
public Transform[] patrolPoints;
public float chaseRange = 10f, attackRange = 2f;
NavMeshAgent agent;
Transform player;
int patrolIndex;
void Start()
{
agent = GetComponent<NavMeshAgent>();
player = GameObject.FindWithTag("Player").transform;
}
void Update()
{
float dist = Vector3.Distance(transform.position, player.position);
switch (currentState)
{
case AIState.Idle:
if (dist < chaseRange) currentState = AIState.Chase;
else if (patrolPoints.Length > 0) currentState = AIState.Patrol;
break;
case AIState.Patrol:
agent.SetDestination(patrolPoints[patrolIndex].position);
if (!agent.pathPending && agent.remainingDistance <= agent.stoppingDistance)
patrolIndex = (patrolIndex + 1) % patrolPoints.Length;
if (dist < chaseRange) currentState = AIState.Chase;
break;
case AIState.Chase:
agent.SetDestination(player.position);
if (dist < attackRange) currentState = AIState.Attack;
else if (dist > chaseRange * 1.5f) currentState = AIState.Patrol;
break;
case AIState.Attack:
agent.isStopped = true;
if (dist > attackRange) { agent.isStopped = false; currentState = AIState.Chase; }
break;
}
}
}
行为树节点
public enum NodeState { Running, Success, Failure }
public abstract class BTNode { public abstract NodeState Evaluate(); }
public class Selector : BTNode
{
BTNode[] children;
public Selector(params BTNode[] children) { this.children = children; }
public override NodeState Evaluate()
{
foreach (var child in children)
{
var result = child.Evaluate();
if (result != NodeState.Failure) return result;
}
return NodeState.Failure;
}
}
public class Sequence : BTNode
{
BTNode[] children;
public Sequence(params BTNode[] children) { this.children = children; }
public override NodeState Evaluate()
{
foreach (var child in children)
{
var result = child.Evaluate();
if (result != NodeState.Success) return result;
}
return NodeState.Success;
}
}
NavMesh 查询
using UnityEngine;
using UnityEngine.AI;
public class NavMeshQueries : MonoBehaviour
{
public Vector3 GetNearestNavMeshPoint(Vector3 pos, float maxDist)
{
NavMeshHit hit;
return NavMesh.SamplePosition(pos, out hit, maxDist, NavMesh.AllAreas)
? hit.position : pos;
}
public bool IsOnNavMesh(Vector3 pos)
{
NavMeshHit hit;
return NavMesh.SamplePosition(pos, out hit, 0.1f, NavMesh.AllAreas);
}
public bool CanReachTarget(Vector3 start, Vector3 end)
{
NavMeshPath path = new NavMeshPath();
NavMesh.CalculatePath(start, end, NavMesh.AllAreas, path);
return path.status == NavMeshPathStatus.PathComplete;
}
public Vector3 GetRandomNavMeshPoint(Vector3 center, float range)
{
Vector3 dir = Random.insideUnitSphere * range + center;
NavMeshHit hit;
return NavMesh.SamplePosition(dir, out hit, range, NavMesh.AllAreas)
? hit.position : center;
}
}
反模式
- 每帧烘焙 NavMesh ——
BuildNavMesh()开销很大。仅在几何体发生变化时调用。增量更新请使用UpdateNavMesh()。 - 未检查 pathStatus —— 始终检查
agent.pathStatus。部分路径或无效路径会导致 Agent 悄无声息地卡住。 - 未加保护就在 Update 中设置目标位置 —— 每帧重新计算路径会浪费 CPU。仅在目标发生明显移动时更新。
- 在 Agent 上添加 NavMeshObstacle —— 不要给同时带有 NavMeshAgent 的 GameObject 添加 NavMeshObstacle。Agent 已经会相互避让。
- 忘记区域遮罩 —— 未设置适当 Area Mask 的 Agent 可能会穿过受限区域。
- 对所有对象都使用雕刻 —— 雕刻开销很大。对于 Agent 可以自然绕行的物体,请使用不进行雕刻的障碍物。
- 缺少 NavMeshSurface —— 没有 NavMeshSurface,就没有 NavMesh。Agent 将无法移动。
- 未释放 Sentis worker —— 始终在
OnDestroy()中调用worker.Dispose()。 - 在 WebGL 上使用 CPU 后端 —— Burst 会编译为 WASM,导致 ML 推理速度非常慢。
关键 API 速查
| 类 | 命名空间 | 用途 |
|---|---|---|
NavMeshAgent | UnityEngine.AI | 寻路和移动 |
NavMeshObstacle | UnityEngine.AI | 动态障碍物 |
NavMesh | UnityEngine.AI | 静态查询和采样 |
NavMeshPath | UnityEngine.AI | 计算出的路径数据 |
NavMeshHit | UnityEngine.AI | 射线检测/采样结果 |
NavMeshSurface | Unity.AI.Navigation | NavMesh 烘焙 |
NavMeshModifier | Unity.AI.Navigation | 单对象覆盖设置 |
NavMeshModifierVolume | Unity.AI.Navigation | 基于体积的覆盖设置 |
NavMeshLink | Unity.AI.Navigation | 表面连接 |
ModelAsset | Unity.Sentis | ONNX 模型引用 |
ModelLoader | Unity.Sentis | 运行时模型加载 |
Worker | Unity.Sentis | 推理引擎 |
BackendType | Unity.Sentis | GPUCompute、CPU、GPUPixel |
Tensor<T> | Unity.Sentis | 输入/输出数据 |
相关技能
unity-foundations—— GameObject、组件、场景层级unity-scripting—— C# 脚本模式、MonoBehaviour 生命周期unity-physics—— 碰撞体、射线检测、与 NavMesh 的物理集成