Skip to main content

Navmesh

A Types.Pathfinder over Roblox's PathfindingService. One Path instance per navmesh, created in new with the agent parameters and reused for every FindPath, so make one per agent rather than one per plan. Never share one between agents: ComputeAsync yields, so a second agent's plan would overwrite the waypoints the first is about to read.

Name is "Navmesh", which Ladder uses in its reasons. Blocked fires whenever the Path instance reports its last computed path blocked, so a Navigator re-plans when a door closes or a part moves into the way instead of waiting for the mover's stuck check.

Functions​

new​

Navmesh.new(options: NavmeshOptions?) → Navmesh

Types

interface NavmeshOptions {
AgentRadius: number?--

Passed to CreatePath. Default 2.

AgentHeight: number?--

Passed to CreatePath. Default 5.

AgentCanJump: boolean?--

Passed to CreatePath. Default false.

AgentCanClimb: boolean?--

Passed to CreatePath. Default false.

WaypointSpacing: number?--

Passed to CreatePath. Default 2.

Costs: {[string]: number}?--

Material and modifier costs passed to CreatePath. Default {}. The VLUXYAI_SAFE label of a SafeAreas area is always added at math.huge unless you set it yourself.

Simplify: boolean?--

Run Navmesh.Simplify over every path. Default true.

SimplifyAngle: number?--

Degrees: a waypoint whose turn is smaller than this is shaved off by Navmesh.Simplify. Default 8.

CollapseLabels: boolean?--

Run Navmesh.CollapseLabels over every path, so a PathfindingModifier volume that labels several waypoints in a row yields one labelled step, like a link. Default true.

StopBefore: number?--

Run Navmesh.StopBefore with this many studs, so the agent stops at the waypoint before a doorway instead of inside the closed door. 0 turns it off. Default 3.

Closest: number?--

Accept a ClosestNoPath result whose last waypoint is within this many horizontal studs of the goal, such as a player standing closer to a wall than the agent's radius. 0 turns it off. Default 4.

}

Creates the Path instance through PathfindingService:CreatePath.

Errors

TypeDescription
"unknown option"A key that is not in `NavmeshOptions`.

Simplify​

Navmesh.Simplify(
path: Path,
angle: number?--

Degrees; a step turning less than this is dropped. Default 8.

) → Path--

A new path; the input is not modified.

Shaves off interior Walk steps that turn less than angle from the line through the last kept step, so a mover walks a few long legs instead of stopping to turn at every 2-stud waypoint of a gentle curve. Pure.

Always kept: the first and last step, every Jump or Custom step, every step with a Label, and the step immediately before a Jump (the jump origin matters). A path of two or fewer steps comes back as a copy.

CollapseLabels​

Navmesh.CollapseLabels(path: Path) → Path--

A new path; the input is not modified.

Merges each run of consecutive steps that share a Label into the first of them, keeping its position. A PathfindingModifier labels every waypoint inside its volume, and waypoints sit a couple of studs apart, so a doorway would otherwise be two or three "Door" steps and a handler would run at each. A run is broken by an unlabelled step or a different label. Pure.

WithSafeAreas​

Navmesh.WithSafeAreas(costs: {[string]: number}) → {[string]: number}--

A copy with the SafeAreas label at math.huge, unless costs already prices it.

Why a navmesh never plans into an enabled safe area. Pure.

StopBefore​

Navmesh.StopBefore(
path: Path,
distance: number--

Studs. The step before must be at most this far from the labelled one.

) → Path--

A new path; the input is not modified.

Moves each label back onto the plain Walk step before it, when that step is within distance, so the agent stops outside a doorway rather than walking into the closed door to reach a waypoint inside it. The labelled step it came from becomes a plain Walk, kept so the agent still walks through. A step after a Jump, a labelled one, or one too far away keeps its label. Run it before Navmesh.Simplify, whose dropped waypoints would otherwise be the ones to stop at. Pure.

EndsNear​

Navmesh.EndsNear(
path: Path,
goal: Vector3,
distance: number--

Horizontal studs.

) → boolean--

true when the path's last step is within distance of goal, ignoring height.

Whether a partial path gets close enough to count. Pure.

FromWaypoints​

Navmesh.FromWaypoints(waypoints: {PathWaypoint}) → Path

Converts Path:GetWaypoints() output to Steps: Action is the waypoint action's name, and an empty Label or one that is only the floor's material name becomes nil. Roblox labels every waypoint with the material under it ("Plastic", "Grass") when no modifier or link labels it; kept, every step of an ordinary path would share a label and Navmesh.CollapseLabels would merge the whole path into its first step. A modifier label that happens to be a material name is dropped with them, so name modifier regions something else. Pure; any table shaped like a waypoint works.

FindPath​

This is a yielding function. When called, it will pause the Lua thread that called the function until a result is ready to be returned, without interrupting other scripts. Yields
Navmesh.FindPath(
self: Navmesh,
from: Vector3,
to: Vector3,
agent: Agent--

Unused; part of the Types.Pathfinder contract.

) → (
Path?,--

The steps, simplified when Simplify is on.

string?--

On failure: the ComputeAsync error text, the PathStatus name (NoPath, ClosestNoPath, ...) or destroyed.

)

Close​

Navmesh.Close(
self: Navmesh,
step: Step,--

The step a handler refused.

seconds: number--

How long to refuse paths through it.

) → ()

The navmesh is Roblox's, so a link cannot be closed for one agent; instead, for seconds, any path this pathfinder computes that crosses a step with the same label within a few studs (or the same Instance) is reported as no path, closed <label> at <position>. The Navigator calls this when a step handler returns false.

Destroy​

Navmesh.Destroy(self: Navmesh) → ()

Destroys the Path instance and the Blocked signal. FindPath after this returns nil, "destroyed".

Show raw api
{
    "functions": [
        {
            "name": "new",
            "desc": "Creates the `Path` instance through `PathfindingService:CreatePath`.",
            "params": [
                {
                    "name": "options",
                    "desc": "",
                    "lua_type": "NavmeshOptions?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Navmesh"
                }
            ],
            "function_type": "static",
            "errors": [
                {
                    "lua_type": "\"unknown option\"",
                    "desc": "A key that is not in `NavmeshOptions`."
                }
            ],
            "source": {
                "line": 135,
                "path": "lib/Pathfinders/Navmesh.luau"
            }
        },
        {
            "name": "Simplify",
            "desc": "Shaves off interior Walk steps that turn less than `angle` from the line through the last kept\nstep, so a mover walks a few long legs instead of stopping to turn at every 2-stud waypoint of\na gentle curve. Pure.\n\nAlways kept: the first and last step, every Jump or Custom step, every step with a Label, and\nthe step immediately before a Jump (the jump origin matters). A path of two or fewer steps\ncomes back as a copy.",
            "params": [
                {
                    "name": "path",
                    "desc": "",
                    "lua_type": "Path"
                },
                {
                    "name": "angle",
                    "desc": "Degrees; a step turning less than this is dropped. Default `8`.",
                    "lua_type": "number?"
                }
            ],
            "returns": [
                {
                    "desc": "A new path; the input is not modified.",
                    "lua_type": "Path"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 197,
                "path": "lib/Pathfinders/Navmesh.luau"
            }
        },
        {
            "name": "CollapseLabels",
            "desc": "Merges each run of consecutive steps that share a `Label` into the first of them, keeping\nits position. A `PathfindingModifier` labels every waypoint inside its volume, and waypoints\nsit a couple of studs apart, so a doorway would otherwise be two or three \"Door\" steps and a\nhandler would run at each. A run is broken by an unlabelled step or a different label. Pure.",
            "params": [
                {
                    "name": "path",
                    "desc": "",
                    "lua_type": "Path"
                }
            ],
            "returns": [
                {
                    "desc": "A new path; the input is not modified.",
                    "lua_type": "Path"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 235,
                "path": "lib/Pathfinders/Navmesh.luau"
            }
        },
        {
            "name": "WithSafeAreas",
            "desc": "Why a navmesh never plans into an enabled safe area. Pure.",
            "params": [
                {
                    "name": "costs",
                    "desc": "",
                    "lua_type": "{ [string]: number }"
                }
            ],
            "returns": [
                {
                    "desc": "A copy with the [SafeAreas] label at `math.huge`, unless `costs` already prices it.",
                    "lua_type": "{ [string]: number }"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 258,
                "path": "lib/Pathfinders/Navmesh.luau"
            }
        },
        {
            "name": "StopBefore",
            "desc": "Moves each label back onto the plain `Walk` step before it, when that step is within\n`distance`, so the agent stops outside a doorway rather than walking into the closed door to\nreach a waypoint inside it. The labelled step it came from becomes a plain `Walk`, kept so\nthe agent still walks through. A step after a `Jump`, a labelled one, or one too far away\nkeeps its label. Run it before [Navmesh.Simplify], whose dropped waypoints would otherwise be\nthe ones to stop at. Pure.",
            "params": [
                {
                    "name": "path",
                    "desc": "",
                    "lua_type": "Path"
                },
                {
                    "name": "distance",
                    "desc": "Studs. The step before must be at most this far from the labelled one.",
                    "lua_type": "number"
                }
            ],
            "returns": [
                {
                    "desc": "A new path; the input is not modified.",
                    "lua_type": "Path"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 279,
                "path": "lib/Pathfinders/Navmesh.luau"
            }
        },
        {
            "name": "EndsNear",
            "desc": "Whether a partial path gets close enough to count. Pure.",
            "params": [
                {
                    "name": "path",
                    "desc": "",
                    "lua_type": "Path"
                },
                {
                    "name": "goal",
                    "desc": "",
                    "lua_type": "Vector3"
                },
                {
                    "name": "distance",
                    "desc": "Horizontal studs.",
                    "lua_type": "number"
                }
            ],
            "returns": [
                {
                    "desc": "`true` when the path's last step is within `distance` of `goal`, ignoring height.",
                    "lua_type": "boolean"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 314,
                "path": "lib/Pathfinders/Navmesh.luau"
            }
        },
        {
            "name": "FromWaypoints",
            "desc": "Converts `Path:GetWaypoints()` output to Steps: `Action` is the waypoint action's name, and an\nempty `Label` or one that is only the floor's material name becomes `nil`. Roblox labels every\nwaypoint with the material under it (`\"Plastic\"`, `\"Grass\"`) when no modifier or link labels\nit; kept, every step of an ordinary path would share a label and [Navmesh.CollapseLabels]\nwould merge the whole path into its first step. A modifier label that happens to be a material\nname is dropped with them, so name modifier regions something else. Pure; any table shaped\nlike a waypoint works.",
            "params": [
                {
                    "name": "waypoints",
                    "desc": "",
                    "lua_type": "{ PathWaypoint }"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Path"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 355,
                "path": "lib/Pathfinders/Navmesh.luau"
            }
        },
        {
            "name": "FindPath",
            "desc": "",
            "params": [
                {
                    "name": "self",
                    "desc": "",
                    "lua_type": "Navmesh"
                },
                {
                    "name": "from",
                    "desc": "",
                    "lua_type": "Vector3"
                },
                {
                    "name": "to",
                    "desc": "",
                    "lua_type": "Vector3"
                },
                {
                    "name": "agent",
                    "desc": "Unused; part of the [Types.Pathfinder] contract.",
                    "lua_type": "Agent"
                }
            ],
            "returns": [
                {
                    "desc": "The steps, simplified when `Simplify` is on.",
                    "lua_type": "Path?"
                },
                {
                    "desc": "On failure: the `ComputeAsync` error text, the `PathStatus` name (`NoPath`, `ClosestNoPath`, ...) or `destroyed`.",
                    "lua_type": "string?"
                }
            ],
            "function_type": "static",
            "yields": true,
            "source": {
                "line": 382,
                "path": "lib/Pathfinders/Navmesh.luau"
            }
        },
        {
            "name": "Close",
            "desc": "The navmesh is Roblox's, so a link cannot be closed for one agent; instead, for `seconds`,\nany path this pathfinder computes that crosses a step with the same label within a few\nstuds (or the same `Instance`) is reported as no path, `closed <label> at <position>`. The\n[Navigator] calls this when a step handler returns `false`.",
            "params": [
                {
                    "name": "self",
                    "desc": "",
                    "lua_type": "Navmesh"
                },
                {
                    "name": "step",
                    "desc": "The step a handler refused.",
                    "lua_type": "Step"
                },
                {
                    "name": "seconds",
                    "desc": "How long to refuse paths through it.",
                    "lua_type": "number"
                }
            ],
            "returns": [],
            "function_type": "static",
            "source": {
                "line": 476,
                "path": "lib/Pathfinders/Navmesh.luau"
            }
        },
        {
            "name": "Destroy",
            "desc": "Destroys the `Path` instance and the `Blocked` signal. `FindPath` after this returns\n`nil, \"destroyed\"`.",
            "params": [
                {
                    "name": "self",
                    "desc": "",
                    "lua_type": "Navmesh"
                }
            ],
            "returns": [],
            "function_type": "static",
            "source": {
                "line": 491,
                "path": "lib/Pathfinders/Navmesh.luau"
            }
        }
    ],
    "properties": [],
    "types": [
        {
            "name": "NavmeshOptions",
            "desc": "",
            "fields": [
                {
                    "name": "AgentRadius",
                    "lua_type": "number?",
                    "desc": "Passed to `CreatePath`. Default `2`."
                },
                {
                    "name": "AgentHeight",
                    "lua_type": "number?",
                    "desc": "Passed to `CreatePath`. Default `5`."
                },
                {
                    "name": "AgentCanJump",
                    "lua_type": "boolean?",
                    "desc": "Passed to `CreatePath`. Default `false`."
                },
                {
                    "name": "AgentCanClimb",
                    "lua_type": "boolean?",
                    "desc": "Passed to `CreatePath`. Default `false`."
                },
                {
                    "name": "WaypointSpacing",
                    "lua_type": "number?",
                    "desc": "Passed to `CreatePath`. Default `2`."
                },
                {
                    "name": "Costs",
                    "lua_type": "{ [string]: number }?",
                    "desc": "Material and modifier costs passed to `CreatePath`. Default `{}`. The `VLUXYAI_SAFE` label of a [SafeAreas] area is always added at `math.huge` unless you set it yourself."
                },
                {
                    "name": "Simplify",
                    "lua_type": "boolean?",
                    "desc": "Run [Navmesh.Simplify] over every path. Default `true`."
                },
                {
                    "name": "SimplifyAngle",
                    "lua_type": "number?",
                    "desc": "Degrees: a waypoint whose turn is smaller than this is shaved off by [Navmesh.Simplify]. Default `8`."
                },
                {
                    "name": "CollapseLabels",
                    "lua_type": "boolean?",
                    "desc": "Run [Navmesh.CollapseLabels] over every path, so a `PathfindingModifier` volume that labels several waypoints in a row yields one labelled step, like a link. Default `true`."
                },
                {
                    "name": "StopBefore",
                    "lua_type": "number?",
                    "desc": "Run [Navmesh.StopBefore] with this many studs, so the agent stops at the waypoint before a doorway instead of inside the closed door. `0` turns it off. Default `3`."
                },
                {
                    "name": "Closest",
                    "lua_type": "number?",
                    "desc": "Accept a `ClosestNoPath` result whose last waypoint is within this many horizontal studs of the goal, such as a player standing closer to a wall than the agent's radius. `0` turns it off. Default `4`."
                }
            ],
            "source": {
                "line": 61,
                "path": "lib/Pathfinders/Navmesh.luau"
            }
        }
    ],
    "name": "Navmesh",
    "desc": "A [Types.Pathfinder] over Roblox's `PathfindingService`. One `Path` instance per navmesh, created\nin `new` with the agent parameters and reused for every `FindPath`, so make one per agent rather\nthan one per plan. Never share one between agents: `ComputeAsync` yields, so a second agent's\nplan would overwrite the waypoints the first is about to read.\n\n`Name` is `\"Navmesh\"`, which [Ladder] uses in its reasons. `Blocked` fires whenever the\n`Path` instance reports its last computed path blocked, so a [Navigator] re-plans when a door\ncloses or a part moves into the way instead of waiting for the mover's stuck check.",
    "source": {
        "line": 126,
        "path": "lib/Pathfinders/Navmesh.luau"
    }
}