引言
在 Unity 游戏开发中,实现智能的 AI 角色移动是提升游戏体验的关键。Unity 提供的 AI Navigation 系统,能够帮助开发者轻松创建能够自主寻路、规避障碍、跨越特殊地形的角色。无论你是初学者还是有经验的开发者,掌握这套系统都能让你在游戏 AI 设计上事半功倍。
本文将基于官方文档和最新特性,系统性地介绍 Unity AI Navigation 的核心功能、使用方法和最佳实践,并附带实际案例和代码示例。
一、AI Navigation 系统简介
AI Navigation 是 Unity 2022.2 之后推出的全新导航系统,取代了旧版的导航功能。该系统基于 导航网格(NavMesh),允许角色在场景中智能移动,支持动态障碍物、跨越链接、区域成本控制等高级功能。
主要组件概览:
| 组件 | 功能 |
|---|---|
| NavMesh Surface | 定义可行走区域 |
| NavMesh Agent | 控制角色的移动与寻路 |
| NavMesh Obstacle | 定义动态或静态障碍物 |
| OffMesh Link | 创建跨越非行走区域的链接 |
| NavMesh Modifier | 调整物体在烘焙时的行为 |
| NavMesh Link | 连接不同 NavMesh 表面 |
二、导航系统的核心概念
1. 导航网格(NavMesh)
NavMesh 是由场景几何体自动生成的凸多边形网格,表示角色可以行走的区域。每个多边形之间记录了邻接关系,方便进行全局寻路。
2. 全局寻路与局部避障
-
全局寻路:使用 A* 算法在 NavMesh 上计算起点到终点的最优路径。
-
局部避障:使用 RVO(互惠速度障碍)算法,预测并避免与其他移动角色或障碍物碰撞。
3. 导航区域与成本
你可以为不同区域(如水面、草地、道路)设置不同的行走成本。高成本区域会被尽量避免,从而控制角色的路径选择。
4. 动态障碍与雕刻(Carving)
动态障碍物可以选择是否在 NavMesh 上"雕刻"出空洞,从而影响全局路径规划。推荐对静止障碍启用雕刻,对移动障碍仅使用局部避障。
三、如何使用 AI Navigation
步骤一:创建 NavMesh
-
选中场景中需要导航的静态物体。
-
添加 NavMesh Surface 组件。
-
设置代理类型、区域类型等参数。
-
点击 Bake 生成 NavMesh。
步骤二:创建 NavMesh Agent
-
创建一个角色(例如一个圆柱体)。
-
添加 NavMesh Agent 组件。
-
编写简单脚本设置目标点:
csharp
using UnityEngine;
using UnityEngine.AI;
public class MoveTo : MonoBehaviour
{
public Transform goal;
void Start()
{
NavMeshAgent agent = GetComponent<NavMeshAgent>();
agent.destination = goal.position;
}
}
步骤三:添加动态障碍
-
创建一个立方体作为障碍物。
-
添加 NavMesh Obstacle 组件。
-
启用 Carve 选项(如果是静止障碍)。
步骤四:创建 OffMesh 链接(如跳跃点)
-
创建两个标记物体作为起点和终点。
-
添加 OffMesh Link 组件。
-
分别指定起点和终点。
四、动画与导航的结合
为了让角色移动更自然,你需要将 NavMesh Agent 与 Animator 结合使用:
csharp
[RequireComponent(typeof(NavMeshAgent), typeof(Animator))]
public class LocomotionSimpleAgent : MonoBehaviour
{
Animator anim;
NavMeshAgent agent;
void Start()
{
anim = GetComponent<Animator>();
agent = GetComponent<NavMeshAgent>();
agent.updatePosition = false;
}
void Update()
{
Vector3 worldDelta = agent.nextPosition - transform.position;
// 转换到本地坐标系并传递给 Animator
// ...
anim.SetBool("move", shouldMove);
anim.SetFloat("velx", velocity.x);
anim.SetFloat("vely", velocity.y);
}
void OnAnimatorMove()
{
transform.position = agent.nextPosition;
}
}
五、常用技巧与常见问题
✅ 推荐做法:
-
对静止障碍物启用 Carve,对移动障碍物仅使用局部避障。
-
使用 Area Mask 控制不同角色可进入的区域。
-
将动画控制与导航分离,避免位置竞争。
❌ 避免事项:
-
不要在同一物体上同时启用 NavMesh Agent 和 NavMesh Obstacle。
-
避免在物理刚体和非动力学 NavMesh Agent 之间出现竞争移动。
🔧 调试工具:
-
使用 AI Navigation Overlay 可视化 NavMesh、路径、障碍物。
-
查看 Navigation Window 中的 Agents 和 Areas 设置。
六、实战示例:巡逻与点击移动
点击移动脚本:
csharp
public class ClickToMove : MonoBehaviour
{
NavMeshAgent agent;
void Start() => agent = GetComponent<NavMeshAgent>();
void Update()
{
if (Input.GetMouseButtonDown(0))
{
RaycastHit hit;
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit))
agent.destination = hit.point;
}
}
}
巡逻脚本:
csharp
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();
}
}
七、总结
Unity 的 AI Navigation 系统提供了一套完整、高效、可扩展的角色导航解决方案。无论是简单的点击移动、复杂的动态避障,还是与动画系统的深度集成,它都能胜任。随着 Unity 版本的更新,该系统也在不断优化,建议开发者持续关注官方文档和更新日志。
本文内容基于 Unity AI Navigation 1.1.1 版本整理,部分示例代码来自官方文档,适用于 Unity 2022.2+ 版本。
如果你对某个功能有更深入的疑问,或希望了解更复杂的应用场景,欢迎在评论区留言讨论!