Tutorial 10 - 3D NavLinks + volumetric NavArea modifiers
TL;DR: LCM Nav3D ships
ULcmNavLinkComponent for vertical ladders/jump
shafts/teleporters (3D-advantage over Recast's surface-projected links)
and ALcmNavAreaModifier for volumetric cost overlays (storm
clouds, water volumes, danger zones, preferred lanes). Both
auto-register on BeginPlay; query via
ULcmNavAreaQueryLibrary from BP or C++.
The 3D-advantage angle
Unreal's stock UNavLinkCustomComponent is fine for
flat NavLinks projected onto the Recast navmesh.
But:
- Vertical ladders spanning 3 floors → Recast needs the navmesh at every floor + the link projects to those poly centres
- Drop-down jumps from a rooftop to a balcony at Z=−500 → Recast clamps the endpoints to nearest navmesh polygons
- Teleporters between Z=200 and Z=2000 → completely outside Recast's representation
LCM Nav3D flying pawns can use any two world-space points for the link endpoints. The components below surface that capability so designers don't have to hand-roll a 3D-aware link system.
Step 1 - Drop a 3D vertical NavLink (ladder example)
- In the editor, spawn an empty actor (or reuse
ANavLinkProxy). - Add Component → search "LCM Nav Link (3D Vertical)".
- Set on the component:
LinkStart= world position of the ladder bottom (e.g.(0, 0, 0))LinkEnd= world position of the ladder top (e.g.(0, 0, 800)- 8 m vertical)bBidirectional= true (climb up or slide down)bAutoRegisterWithApex= true (default)TraversalCostCm= extra cm-cost of using the ladder (0 = free; e.g.400to make agents prefer a nearby ramp). Queryable in v1 (see Step 3); auto-routing is v2.
That's it. The link is now visible to:
- Stock Unreal nav-system tooling (it implements
INavLinkCustomInterface) - LCM Nav3D's extension registry (queryable via
ULcmNavAreaQueryLibrary)
Step 2 - Drop a volumetric NavArea modifier (water example)
- In the editor, spawn a
ALcmNavAreaModifieractor. - Move + scale the box gizmo to cover your water volume.
- Set:
CostMultiplier=3.0(agents prefer dry routes by 3× cost)AreaTag="Water"(optional designer label)bAutoRegisterWithApex= true
Stack multiple modifiers in the same volume - costs multiply:
| Volume | Cost multiplier |
|---|---|
| Water | 3.0 |
| + storm cloud overlapping | × 5.0 |
| Effective in overlap region | 15.0 |
Step 3 - Query from BT / StateTree / Blueprint
// In a BT service tick, or anywhere with C++ access:
const float Cost = ULcmNavAreaQueryLibrary::GetCostMultiplierAt(AgentLocation);
// Or evaluate a planned path's accumulated area cost (multiplicative):
const float PathCost = ULcmNavAreaQueryLibrary::GetCostMultiplierAlongPath(Waypoints);
//.and the additive cm-cost of any priced NavLinks the route uses:
const float LinkCost = ULcmNavAreaQueryLibrary::GetNavLinkTraversalCostAlongPath(Waypoints);
// Combine however your AI weighs routes, e.g. compare two candidate paths and pick
// the one with the lower (length * PathCost + LinkCost).
// Find the nearest ladder for "approach the ladder" patterns:
ULcmNavLinkComponent* Nearest =
ULcmNavAreaQueryLibrary::FindNearestNavLink(AgentLocation, /*MaxDist*/ 500.0f);
if (Nearest)
{
FVector LadderStart, LadderEnd;
ENavLinkDirection::Type Dir;
Nearest->GetLinkData(LadderStart, LadderEnd, Dir);
// Have FlyTo task move to LadderStart, then trigger the link traversal.
}
All of these are Blueprint-callable via the standard "LCM Navigation | Bridge" category.
Solver integration (v1 vs v2)
v1 (this release):
- NavLinks register with the UE5 NavSystem → stock
UBTTask_MoveToworkflows that involve smart-links work - NavArea cost multipliers and NavLink
TraversalCostCmare queryable (GetCostMultiplierAlongPath/GetNavLinkTraversalCostAlongPath) but the LCM Nav3D A* solver doesn't yet incorporate them into its own path-cost evaluation - Buyer pattern: use the query library in a BT service to write the
cost-along-path into a blackboard key, then a
LcmDecorator_PathLengthBelow-style decorator gates on it
v2 (deferred):
- Cost multipliers plumbed into the LCM Nav3D A* leaf-cost evaluation → paths actually route around / through preferred lanes automatically
- NavLink edges added to the macro graph so the solver plans through them
- An additional cost channel under the same bounded-LSB parity discipline as the existing sweep-penalty plumbing
v1 is the placement + registry + query surface; v2 is the solver-side cost integration. The data plane is ready; the planner-side wiring lands when the Marketplace v3.0 ramp justifies the solver-touch budget.
Common patterns
Ladder + drop-down combo
Two ULcmNavLinkComponents on the same actor:
- Ladder: bidirectional,
LinkStart = (0, 0, 0),LinkEnd = (0, 0, 800) - Drop-down: one-way,
LinkStart = (200, 0, 800),LinkEnd = (200, 0, 0),bBidirectional = false
Storm cloud + ground danger
Two ALcmNavAreaModifiers:
- Storm cloud at Z=300.800, CostMultiplier 5.0, Tag "Storm"
- Danger zone at Z=0.150, CostMultiplier 10.0, Tag "Combat"
Agents flying at Z=200 see normal cost; flying at Z=400 see 5× cost; flying through ground combat at Z=50 see 10× cost.
Preferred lane
Single ALcmNavAreaModifier with
CostMultiplier = 0.5. LCM Nav3D paths bias toward this
volume when the v2 solver integration lands.
Acceptance test (manual)
- Drop a
ULcmNavLinkComponentwith LinkStart at(0,0,0), LinkEnd at(0,0,500), andTraversalCostCm = 400. - In a Blueprint test actor:
Print String (ULcmNavAreaQueryLibrary::GetRegisteredLinkCount)→ should print1. - Move the test actor near
(0,0,0). CallFindNearestNavLink(actor.location, 1000)→ returns your component. GetNavLinkTraversalCostAlongPath([(0,0,0),(0,0,500)])→ returns400. A path that stays away from the link (e.g.[(5000,0,0),(6000,0,0)]) → returns0.- Drop a
ALcmNavAreaModifiercovering(0,0,250)with CostMultiplier 5.0. GetCostMultiplierAt((0,0,250))→ returns5.0. At(0,0,800)→ returns1.0.
Related LCM Nav3D-unique surfaces
ULcmTacticalQueryLibrary::GetSweepPenaltyAt- §P9.3 dynamic-obstacle risk byte (orthogonal to NavArea modifiers; both apply)LCM_BTDecorator_PathLengthBelow- LCM Nav3D path-length predicate; complements cost-along-pathLCM_BTService_ThreatFieldSampler- write SweepPenalty into BB; pair with cost-multiplier write for full risk-aware AI