NavMesh and NavMeshAgent
NavMesh queries a baked navigation graph. NavMeshAgent moves a root
GameObject with an enabled agent component and an enabled assigned surface.
Explicit Navigation Links can connect that surface to others.
Path Queries
NavMesh.FindPath(sx, sy, sz, ex, ey, ez) returns a table of Vec3 points. A
successful result is complete and contains at most 32 points. An empty table
means no complete route fits the graph and path limit.
Endpoints must be near a baked sample: horizontally within half a cell diagonal and vertically within half Cell Height, with a minimum vertical tolerance of 0.05 units. Positions on a baked connection are also supported. The last point is a baked node, not the unchecked original world position. An arbitrary point outside the graph is rejected rather than appended to the route.
NavMesh.SamplePosition(x, y, z, maxDistance[, surfaceGameObjectId]) returns
found, sampleX, sampleY, sampleZ. It finds the nearest baked node within the
specified 3D distance. Its optional surface ID restricts sampling to that exact
surface. Sampling does not prove that a route exists from the agent to that node;
always check the result of NavMeshAgent.SetDestination too.
Agent Movement
Attach this script to the root GameObject with the agent component. Assign the target GameObject ID in its Lua properties. A small projection distance can help when the target is between grid samples; keep it small enough to avoid selecting a different floor.
targetGameObjectId = -1
projectionDistance = 0.75
function Start(gameObjectId)
if targetGameObjectId < 0 then
Log.Print("Assign a target GameObject first.")
return
end
local target = Transform.GetPosition(targetGameObjectId)
if target == nil then
return
end
local found, x, y, z = NavMesh.SamplePosition(
target.x, target.y, target.z, projectionDistance)
if not found or not NavMeshAgent.SetDestination(gameObjectId, x, y, z) then
NavMeshAgent.Stop(gameObjectId)
Log.Print("No complete navigation route to this target.")
end
end
Send a new destination when the target changes, not every frame: a successful
request restarts the route and its acceleration. A failed request returns
false and preserves any previous route. Call NavMeshAgent.Stop if failure
should cancel movement, as the example does.
Queries include IsMoving, HasPath, HasReachedDestination, IsOnNavMesh,
GetRemainingDistance, GetSpeed, and GetPathStatus.
NavMeshAgent.PathComplete means a complete route was calculated;
NavMeshAgent.PathInvalid means no valid route is owned.
- Acceleration zero applies the configured speed immediately.
- Stopping Distance applies to the last waypoint. Intermediate points use a small tolerance.
NavMeshAgent.Stopstops movement and resets speed, while retaining the calculated route. It does not report arrival unless the route was already completed.IsOnNavMeshandGetRemainingDistanceuse the GameObject's current position.- If another script moves an active agent, navigation recalculates from that position to the existing goal on its next update. If the new position cannot reach the goal, movement stops and the route becomes invalid.
- Disabled agents stop and discard their active route when navigation next updates. Send a new destination after enabling them again.
Connected Surfaces and Limits
The assigned surface anchors the agent's navigation network. Agents may use
surfaces reachable through explicit directed Navigation Links. A one-way link
does not permit the reverse trip, and disconnected surfaces remain inaccessible.
NavMesh.SamplePosition still uses its exact optional surface filter.
The graph is static: baked once when entering Play Mode and during PS1 export. Moving a wall or changing navigation geometry during play does not rebuild it. Navigation writes the root Transform and does not provide dynamic obstacle avoidance, physics collision response, jump animations, or ladder traversal. Use a single movement owner for the agent rather than also driving it with a Character Controller or another movement script.
See Rooms, Portals, and Navigation for setup, settings, links, and troubleshooting.