Navigation3D core concepts
Before you use Navigation3D, understand: navigation domains, SVO structure, chunks and radius tiers, coordinates, the two pathfinding layers, and how a query becomes a trajectory.
Five navigation domains
The unified facade routes by NavigationDomain:
| Domain | Meaning | Backend |
|---|---|---|
Ground | Ground navmesh | Detour (RecastNavigation) |
Air | Free flight space | SVO flight pathfinding |
Hybrid | Cross-domain composite path | Domain-link coarse plan + per-segment refine |
Underwater | Underwater free space | SVO (classified as underwater inside a region) |
Climb | Climbable slopes / walls | Climb surface graph |
IsVolumetricDomain is Air || Underwater; IsSurfaceDomain is Ground || Climb. Underwater regions can work with
Water via UnderwaterRegionRequestBus or Hybrid’s underwater AABB.
SVO: sparse voxel octree
Each chunk is one SvoVolume: Morton-sorted node layers plus a leaf array. After build it is immutable and safe for concurrent reads.
Layers and leaves
layers[0]is the finest normal layer; the root is the top layer.- Layer-0
Mixednodes point atSvoLeafNode; each leaf block is4×4×4 = 64subvoxels in a 64-bit occupancy mask. LeafVoxelSize(default 0.5 m) is the finest edge; leaf-block size = voxel × 4; chunk edge should matchChunkSize.
Node occupancy (NodeFlags)
| Flag | Meaning | Pathfinding |
|---|---|---|
Free | Fully empty | Graph vertex; can span in one step |
Solid | Fully occupied | Pruned |
Mixed | Partially occupied | Has children; layer-0 Mixed points at a leaf mask |
Graph vertices are Free normal-layer nodes or Free leaf subvoxels, with six-connected face adjacency (±X / ±Y / ±Z).
Chunks and border links
A navigation volume is usually larger than one chunk. Space is tiled by ChunkSize (default 128 m), one SVO per chunk:
- Supports local rebuild (dirty chunks only) and streaming (page by active region).
- Adjacent chunks pair free face cells on shared borders into border links (portals)—abstract edges for cross-chunk search.
Radius tiers
At build time each radius in RadiusTiers dilates occupancy and produces its own SVO set. At query time the system picks the smallest tier whose radius ≥ agent radius.
- Each chunk is voxelized once; tiers share occupancy and only repeat dilate + aggregate.
- Default is
{ 0.5 }. For multiple body sizes, list ascending tiers.
Coordinate conventions
Single precision loses accuracy on large maps, so a volume holds:
m_worldAnchor: double-precision world anchor (usually the volume AABB min corner).- Volume-local single precision: used inside the SVO and on trajectory points.
Bridging rules:
- Single-precision methods on
NavigationVolumeRequestBus/FlightNavigationRequestBus: absolute world coordinates; components add/subtract the anchor at the boundary. *D(double) methods: exchangeAZ::Vector3dabsolute world coordinates directly.NavigationQueryRequestBus(facade): alwaysAZ::Vector3d.- L1
SvoVolume/ trajectory points: volume-local single precision.
Prefer the facade’s double-precision APIs in gameplay code.
Two pathfinding layers
Single chunk: Lazy Theta*
Expands on the six-connected free-cell graph with optimistic line-of-sight shortcuts, verified with CapsuleFree on dequeue; failure falls back to a normal A* parent. Supports Init + Step(budget) across frames.
Result codes: Success / StartOccupied / GoalOccupied / Unreachable / ExpansionLimit.
Cross chunk: HPA*
Outer A* searches an abstract graph of start, goal, and border-link portals; each leg nests Lazy Theta*. With border links, use graph search; otherwise fall back to a start→goal corridor sliced by chunk.
Cost and tabu
Edge cost stacks size modulation, height-band penalties, runtime cost fields (≥ ~1e9 is no-fly), and fixed-wing turn penalties. Edges rejected by post-process become tabu and feed replan.
Query data flow
Query from/to/config
→ Snapshot volume (chunks + border links + cost field)
→ Pick radius tier by agentRadius
→ Pathfind (Lazy Theta* / HPA*) → geometric path
→ Post-process Hover / FixedWing → FlightTrajectory
│ (segment fails)
└─ tabu replan (bounded) → else straight-line fallback
→ volume-local → world (add anchor) → FlightPath / NavigationPath
| Type | Meaning |
|---|---|
FlightPath / FlightPathD | Flight polyline: m_waypoints + m_length |
FlightTrajectory | Followable trajectory: position / tangent / speed hints |
NavigationPath | Facade cross-domain path: waypoints carry m_domain and takeoff/land flags |
FlightFailureReason | None / StartOccupied / GoalOccupied / Unreachable / ExpansionLimit / PostProcessFailed / NoVolume |
Determinism contract
Identical inputs (volume snapshot, seed, config) produce byte-identical results. Therefore:
- Offline bake matches runtime build;
- Async matches sync; scheduling only changes completion time;
- Unit tests can assert exact paths.
Next steps
- Components — map concepts onto fields
- Querying — run the various queries
- Programmatic API — use the L1 core directly