目录
基础实现方案
-
获取导航路径点
- 使用
NavMesh.CalculatePath()
方法计算起点到终点的路径 - 该方法返回一个
NavMeshPath
对象,包含路径点数组(corners) - 示例代码:
NavMeshPath path = new NavMeshPath(); bool pathFound = NavMesh.CalculatePath(startPosition, endPosition, NavMesh.AllAreas, path); if(pathFound && path.corners.Length > 1) { // 处理路径点 }
- 使用
-
可视化渲染方式
- LineRenderer方案:
- 创建带有LineRenderer组件的游戏对象
- 将路径点数组赋值给LineRenderer的positions属性
- 可自定义线条颜色、宽度和材质
- Gizmos绘制方案:
- 在OnDrawGizmos方法中使用Gizmos.DrawLine逐段绘制
- 适合编辑器调试,但不适合运行时显示
- LineRenderer方案:
-
动态更新处理
- 在Update或协程中定期检测角色位置变化
- 当角色移动超过阈值时重新计算路径
- 平滑过渡处理避免路径突然跳变
进阶优化方案
-
路径美化处理
- 使用贝塞尔曲线平滑路径拐角
- 添加路径箭头指示方向
- 实现渐变色效果表示路径热度
-
性能优化
- 对象池管理LineRenderer实例
- 降低路径更新频率(如每0.3秒更新一次)
- 使用JobSystem进行路径计算
-
交互功能增强
- 点击路径点查看详细信息
- 路径拖拽编辑功能
- 多段路径的合并与拆分
应用场景示例
- RPG游戏:显示任务目标路径指引
- 策略游戏:展示单位移动路线
- AR导航:在真实环境中显示虚拟路径
- 教育模拟:演示AI寻路算法过程
注意事项
- 导航网格需要预先烘焙好
- 复杂场景要考虑路径分段加载
- 移动平台注意性能开销
- 处理路径被动态障碍物阻挡的情况
完整实现通常需要结合项目具体需求进行调整,核心是把握好路径获取、渲染更新和性能平衡这三个关键环节。
最近刷到b站up主山长操作库的内容,感觉很有意思,于是就简单整理了一下。注意本文的实现思路完全是按这位up整理的,这里就先放记录在这里,后续如果实际项目有用的到再深入研究。
设置好LineRenderer线组件配置,用于绘制寻路轨迹
代码
新增代码控制寻路轨迹显示
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class NavPathLineRenderer : MonoBehaviour
{
[Header("References")]
[Tooltip("玩家的Transform组件")]
[SerializeField] private Transform player; // 玩家的Transform
[Tooltip("目标点的Transform组件")]
[SerializeField] private Transform target; // 目标的Transform
[Tooltip("用于可视化路径的LineRenderer组件")]
[SerializeField] private LineRenderer line; // 用于绘制路径的LineRenderer组件
[Header("Path Settings")]
[Tooltip("路径线相对于地面的垂直偏移量")]
[SerializeField] private float pathHeightOffset = 0.3f; // 绘制路径时的垂直偏移量(在地面上方)
[Tooltip("每条路径段的分段数,数值越高路径越平滑")]
[Range(1, 20)]
[SerializeField] private int quality = 10; // 每个路径段的分段数
[Tooltip("射线检测的最大高度")]
[SerializeField] private float maxHeight = 10; // 射线最大高度
[Tooltip("路径更新的时间间隔(秒)")]
[SerializeField] private float drawUpdateSpeed = 0.2f; // 路径绘制更新速度
private Coroutine drawCoroutine; // 用于管理路径绘制的协程引用
private void Start()
{
// 确保LineRenderer组件不为空
if (line == null)
{
line = GetComponent<LineRenderer>();
if (line == null)
{
Debug.LogError("LineRenderer component is missing!");
return;
}
}
// 在开始之前停止任何现有的协程
if (drawCoroutine != null)
{
StopCoroutine(drawCoroutine);
}
drawCoroutine = StartCoroutine(DrawNavMeshLine());
}
// 协程:持续绘制NavMesh路径
private IEnumerator DrawNavMeshLine()
{
WaitForSeconds wait = new WaitForSeconds(drawUpdateSpeed); // 等待时间间隔
NavMeshPath path = new NavMeshPath(); // 存储计算路径的NavMeshPath对象
// 只要目标不为空,就持续绘制路径
while (target != null)
{
// 从玩家位置到目标位置计算路径
if (NavMesh.CalculatePath(player.position, target.position, NavMesh.AllAreas, path))
{
// 平滑并绘制路径线条
List<Vector3> newPath = new List<Vector3>(); // 存储平滑后的路径点
// 遍历路径中的每个拐点
for (int i = 0; i < path.corners.Length - 1; i++)
{
// 计算当前路径段的起点和终点(加上高度偏移)
Vector3 currentPoint = path.corners[i] + Vector3.up * maxHeight;
Vector3 nextPoint = path.corners[i + 1] + Vector3.up * maxHeight;
// 细分路径段
for (int j = 0; j < quality; j++)
{
// 计算当前分段点
float t = (1f / quality) * j;
Vector3 calPoint = Vector3.Lerp(currentPoint, nextPoint, t);
RaycastHit hit;
// 向下发射射线检测地面
if (Physics.Raycast(
calPoint,
Vector3.down,
out hit,
Mathf.Infinity,
1 << LayerMask.NameToLayer("Ground")))
{
newPath.Add(hit.point); // 添加有效的地面点到路径
}
}
}
// 添加最终目标位置
newPath.Add(target.position);
// 设置LineRenderer
line.positionCount = newPath.Count;
// 反转路径顺序(从玩家到目标)
for (int i = 0; i < newPath.Count; i++)
{
line.SetPosition(i, newPath[newPath.Count - 1 - i] + Vector3.up * pathHeightOffset);
}
// 更新玩家的NavMeshAgent路径
var agent = player.GetComponent<NavMeshAgent>();
if (agent != null)
{
agent.SetPath(path);
}
}
yield return wait; // 等待下一次更新
}
}
}
使用说明
-
组件配置:
- 将脚本附加到含有LineRenderer组件的游戏对象上
- 在Inspector面板中设置:
- Player:玩家角色(需要NavMeshAgent组件)
- Target:目标点
- Line:用于绘制的LineRenderer组件
-
参数说明:
- 路径高度偏移:控制路径线在地面上方的高度
- 分段质量:数值越高路径越平滑,但性能消耗越大
- 更新速度:控制路径更新的频率
-
注意事项:
- 确保场景中有"Ground"层,用于射线检测
- 玩家对象需要NavMeshAgent组件
- 目标对象需要位于NavMesh可行走区域内
-
应用场景:
- RPG游戏中的任务指引
- 策略游戏的单位移动路径显示
- 导航系统的路径预览功能
挂载代码,配置参数
烘培导航网格
设置地面图层
设置不同地面的优先级,区分不同表面
烘培寻路网格
运行效果
总结
本文提出了一种基于Unity NavMesh的寻路轨迹可视化解决方案。该方案通过LineRenderer组件绘制移动路径,并采用协程机制实现路径的定时更新。主要功能特性包括:路径平滑处理、高度偏移调整以及地面碰撞检测。核心实现技术涉及:
- 使用NavMesh.CalculatePath进行路径计算
- 采用分段插值算法实现路径平滑
- 通过射线检测确保路径与地面贴合
系统支持多项参数配置,可灵活调整路径高度、平滑度及更新频率。该方案适用于:
- RPG游戏的任务指引系统
- 策略游戏的单位移动路径展示
使用前提要求场景中已烘焙导航网格并正确设置地面层级。