3D 导航:傻瓜式上手
照着点就能跑。本页讲 SDGToolSet 当前的 3D 导航玩法:放一个体积(Volume),让某个 Actor 沿自动生成的 3D 路径飞起来。
:::tip 必读前提 SDGToolSet 由 IADataSDG 的授权统一管控。IADataSDG 没激活,导航一律不动(路径不生成、Pawn 不飞、被指定的 Actor 也不动)。先看安装与激活。 :::
30 秒搞懂三种机制
| 机制 | 谁来驱动 | 要不要 Pawn | 适用 |
|---|---|---|---|
| A. 体积驱动指定 Actor | USDGNavDriverSubsystem(世界子系统,自动) | 不需要 | 最简单:让任意 Actor 沿路径走 |
| B. Pawn 跟随指定体积 | Pawn 上的 USDGPathManagerComponent | 需要 | 飞行采集、相机巡航 |
| C. 自动接管(旧行为,默认关) | 同 B,但自动扫描 | 需要 | 采集 Pawn BPP_Nav 的工作方式 |
两条铁律(避免“双重驱动”):
- 体积一旦设了 Navigated Actor,它就只由子系统驱动;任何 Pawn 都会跳过它。
- Pawn 只飞“没指定 Actor”的体积。两套机制的体积集合互不重叠,同一个体积/Actor 不会被驱动两次。
快速开始 A:放一个 Volume + 指定 Actor,让它自己走(最简单,无需 Pawn)
- 放体积:打开 Place Actors(放置 Actor) 面板,搜索
SDG Nav Path Volume,拖进场景。 - 放大体积(关键一步):新放的体积默认只有约 200 × 200 × 200 cm,太小,生成不出路径。用缩放工具(快捷键
R)把它放大到能罩住一片开阔、无遮挡的可飞空间。参考示例关卡Lv_TestToolSet的大小约 2400 × 2350 × 450 cm(X × Y × Z);Z 就是飞行的高度带。把体积摆在没有墙体穿插的空中区域。 - 设体素大小:选中体积 → Details → 分类 SDG ▸ Grid →
VoxelSize填100(cm,默认值;室内可 50~100)。务必远小于体积的最短边。 - 指定被导航的 Actor:Details → 分类 SDG ▸ PathGen →
Navigated Actor,下拉选场景里任意一个 Actor(一个 Cube、StaticMeshActor、相机都行)。建议把它的 Mobility 设为 Movable;就算是静态根,系统也会在运行时自动提升为 Movable。 - 把它加入 IgnoreActors:Details → 分类 SDG ▸ NavPathVolume →
IgnoreActors→ 加一项,选刚才那个被导航的 Actor。否则它自己的碰撞会把体素堵住,路径可能绕不开自己。 - 按 Play(PIE)。
你应该看到:
- 被指定的 Actor 先“瞬移”到路径起点,再沿平滑曲线飞行;
- 飞到终点后停下(默认不循环);
- Output Log 出现:
[SDG][NavDriver][VOL 0] Driving '<你的Actor>' along 1 spline(s).
[SDG][NavDriver] Self-driving 1 assigned-volume group(s).
[SDG][NavDriver] frame 0: '<你的Actor>' at (x, y, z)
不需要放 Pawn。
USDGNavDriverSubsystem在关卡 BeginPlay 时自动发现“带 Navigated Actor 的体积”,建路径并逐帧驱动。
快速开始 B:让一个 Pawn 跟随指定 Volume
前提:目标体积的 Navigated Actor 必须留空(带指定 Actor 的体积由子系统接管,Pawn 会跳过)。
- 放体积:同 A 的第 1~3 步,但
Navigated Actor留空。 - 放 Pawn:Place Actors 搜索
SDG Nav Path Pawn(类ASDGNavPathPawn),拖进场景。它自带PathManager组件。 - 指定要飞的体积:选中 Pawn → Details → 找到
PathManager组件 → 分类 SDG ▸ PathManager →FollowVolumes→ 加一项,选第 1 步那个体积。 - 设速度:选中 Pawn → Details → 分类 Nav ▸ Move →
MoveSpeed填400(cm/s)。bUsePIDController默认关(匀速跟随);打开则用 PID 飞控。 - 按 Play。Pawn 会沿该体积的路径飞行,Output Log:
[SDG][PM] Explicit FollowVolumes: 1 volume(s) to fly.
[SDG][PM] RebuildPaths done: PawnSplines=1 AssignedVolumesSkipped=0 (driven by subsystem) TotalLen=...
:::note 用自己的 Actor + 组件时
如果你不用 ASDGNavPathPawn,而是给自己的 Actor 加 USDGPathManagerComponent 并调用 MoveInsideNavVolume() 驱动:注意 bUseProjectDefaults 默认 true,会在 BeginPlay 用项目设置覆盖你在 Details 里填的 MoveSpeed。要保留 per-instance 速度,把 bUseProjectDefaults 设为 false。
:::
机制 C(进阶,默认关):让 Pawn 自动接管所有“未指定”体积
- 选中 Pawn →
PathManager→ 分类 SDG ▸ PathManager →bAutoDiscoverUnassignedVolumes= true,并保持FollowVolumes为空。 - 这样 Pawn 会飞场景里所有没有 Navigated Actor 的体积。这是采集 Pawn
BPP_Nav的工作方式。 - 优先级:
FollowVolumes非空时永远优先用它(此时忽略 auto-discover)。
必填参数清单
| 场景 | 字段(Details 分类) | 必填? | 起始值 | 一句话说明 |
|---|---|---|---|---|
| 全部 | IADataSDG 已激活 | ✅ 必填 | — | 没激活则一切不动(授权门) |
| A / B | 体积尺寸 | ✅ 必填 | ~2400×2350×450 cm | 必须罩住开阔可飞空间;默认 200³ 太小 |
| A / B | VoxelSize(SDG ▸ Grid) | ✅ 必填 | 100 | 体素边长(cm),远小于体积最短边 |
| A | Navigated Actor(SDG ▸ PathGen) | ✅ 必填 | 选一个 Actor | 谁来走这条路;留空=交给 Pawn |
| A | IgnoreActors(SDG ▸ NavPathVolume) | ⭐ 强烈建议 | 加入被导航 Actor | 防止它自己的碰撞堵住体素 |
| B | FollowVolumes(SDG ▸ PathManager) | ✅ 必填(B) | 加入目标体积 | Pawn 要飞哪些(仅“未指定”的体积) |
| B | MoveSpeed(Nav ▸ Move,Pawn) | 可选 | 400 | 飞行速度(cm/s) |
| C | bAutoDiscoverUnassignedVolumes(SDG ▸ PathManager) | 可选 | false | 开=飞所有未指定体积 |
| 通用 | bLoopAllPaths(SDG ▸ PathManager) | 可选 | false | 走完是否循环 |
| 通用 | bAutoAdvanceNext(SDG ▸ PathManager) | 可选 | true | 当前样条走完自动切下一条 |
| 通用 | RandomSeed(SDG ▸ PathGen) | 可选 | 12345 | 改变随机轨迹 |
| 通用 | bUseRandomPath(SDG ▸ PathGen) | 可选 | true | true=随机起终点;false+自定义端点见下 |
| 通用 | NumPaths(SDG ▸ PathGen) | 可选 | 1 | 生成几条路径 |
| 通用 | bUseCustomEndpoints / CustomStart / CustomGoal(SDG ▸ PathGen) | 可选 | false | 指定固定起终点(需 bUseRandomPath=false) |
机制 A 的飞行速度来自项目设置 → SDG Navigation 的
Movement.SpeedCmPerSec(默认 400 cm/s),不在体积上单独配。
如何开始测试
编辑器内(PIE):直接点 Play。打开 Output Log(菜单 Window ▸ Output Log)核对:
- 机制 A 成功:
[SDG][NavDriver] Self-driving N assigned-volume group(s). - 机制 B 成功:
[SDG][PM] RebuildPaths done: PawnSplines=N ... - 路径质量自检:
[SDG][PM][VOL 0] PathClearance: 0/NN out-of-free (0.0%) Z[...] volZ[...]——越界比例越接近 0% 越好(说明路径没钻地/穿墙)。
命令行 / 无头(进阶):
"<UE_5.8>\Engine\Binaries\Win64\UnrealEditor-Cmd.exe" "<你的工程>.uproject" <地图名> -game -windowed -log
不改关卡就换一条随机轨迹:追加 -dpcvars="sdg.nav.SeedOverride=24680"(≥0 时覆盖所有体积的 RandomSeed)。
排错 / 动不了怎么办
| 症状 | 关键日志 | 解决 |
|---|---|---|
| 完全不动 | IADataSDG is not licensed/loaded; ... DISABLED | IADataSDG 没激活 → 先激活。激活后重进 PIE 即可,无需重启编辑器。 |
| 不动 / 没路径 | [SDG][NavDriver][VOL n] No navigable path generated ... Ensure the volume encloses free space and is at least a few VoxelSize across.(或 Pawn 侧 BuildVoxelGrid failed / PawnSplines=0) | 体积太小、没罩住空地,或 VoxelSize 太大 → 放大体积、确保罩住开阔空间、把 VoxelSize 调小。 |
| Pawn 不动 | [SDG][PM] RebuildPaths done: PawnSplines=0 (no FollowVolumes, auto-discover OFF -> pawn flies nothing). | Pawn 既没设 FollowVolumes,也没开 bAutoDiscoverUnassignedVolumes → 二选一配置。 |
| Pawn 跳过了体积 | [SDG][PM][VOL n] Listed FollowVolume has a NavigatedActor -> owned by USDGNavDriverSubsystem; pawn skips it. | 你让 Pawn 飞了一个“已指定 Actor”的体积(互斥)→ 要么清空该体积的 Navigated Actor,要么换一个未指定体积。 |
| 指定的 Actor 不动 | NavigatedActor '...' unresolved; skipped (no pawn fallback). | 引用的 Actor 被删了 / 在未加载的子关卡里 → 重新指定一个当前关卡里存在的 Actor。 |
| Actor 不动但无报错 | (无) | 目标 Actor 真的无法位移(没有可变换的根组件)→ 换一个有 SceneComponent 根、可移动的 Actor。 |
| 速度像被锁死 / 跟填的不一样 | (无) | 通用组件流里 bUseProjectDefaults=true 会在 BeginPlay 用项目设置覆盖 Details 里的 MoveSpeed → 设 bUseProjectDefaults=false 保留你填的值。 |
行为须知(别被吓到)
- 瞬移到起点:第一帧 Actor / Pawn 会从你摆放的位置跳到“路径起点”,再开始沿线飞——这是正常的,不是 bug。
- 默认不循环:
bLoopAllPaths = false,飞到终点就停。要来回循环就把它设为 true。