Navigation: complete setup
Build, paint, name, script, tune, debug, and ship a complete Vaelis navigation setup without skipping the hard parts.
#The complete model: five pieces, one pipeline
Vaelis navigation is easiest to understand as a pipeline rather than as one button. A scene normally has one shared NavWorld2D; the NavWorld stores the base walkability grid, each NavAgent2D supplies per-agent size/restrictions, and script movement consumes the resulting path.
#End-to-end setup: from empty scene to moving NPC
#Goal: make one NPC walk around walls to the target
Bounds X, Bounds Y, Bounds Width, and Bounds Height. The bounds define the grid region; they do not move the entity's Transform by themselves.32 world units, then reduce it only when a corridor or obstacle genuinely needs more resolution.nav.bake(). Most games bake in the editor once.−/+ brush buttons beside the nav display controls reduce/increase the brush radius.Radius 16, Speed 120, Auto Repath ON, and the default area mask.function onUpdate(dt) {
var target = findFirst("Target");
if (!target) return;
this.navMoveToward(target.x, target.y, 120, {
repathInterval: 0.25,
finalArriveDist: 12,
debug: true
});
}debug:true is used and the debug overlay is visible.#Every navigation editor control, in context
| Control | Where it appears | What it does | Increase / decrease behavior |
|---|---|---|---|
Nav World 2D | GameObject → 2D Object → Nav World 2D | Adds the shared navigation grid component/entity. | One shared world per scene is the normal design. |
Bounds X / Y | Right Inspector → Nav World 2D | Moves the grid rectangle relative to the Nav World entity. | Larger positive/negative values shift the grid rectangle; they do not resize it. |
Bounds W / H | Right Inspector → Nav World 2D | Controls navigation coverage. | Larger = larger navigable region and more cells; smaller = less coverage. |
Cell Size | Right Inspector → Nav World 2D | Controls grid resolution. | Smaller = more precise/narrower features represented, more cells/work. Larger = cheaper, but narrow geometry may disappear into one cell. |
Bake Nav World | Right Inspector → Nav World 2D | Reads eligible Collider2D geometry and produces the base walkability grid. | Run after changing static obstacles unless Dynamic mode is being used. |
Dynamic | Right Inspector → Nav World 2D | Enables automatic rebaking when bake-relevant static geometry changes. | ON = convenience for runtime-changing static-like geometry; OFF = avoid rebake work for mostly-static levels. |
Allow Diagonal | Right Inspector → Nav World 2D | Controls whether A* may use diagonal grid neighbors. | OFF = 4-neighbor grid; ON = diagonals become valid route steps. |
U Walkable | Top editor toolbar; only after Nav World 2D exists | Paints an explicit walkable override. | Brush size is controlled by the nearby −/+ buttons. |
I Blocked | Top editor toolbar; only after Nav World 2D exists | Paints an explicit blocked override. | Same brush-size controls and Alt+click erase behavior. |
O Area | Top editor toolbar; only after Nav World 2D exists | Paints the selected navigation area onto cells. | Area choice appears beside the brush only while Area mode is active. |
Edit → Nav Areas… | Top editor menu Edit | Names the 16 navigation area slots. | Names are used later by nav.areaMask() and nav.areaCosts(). |
Bounds / Cells view buttons | Top toolbar beside nav tools | Switches between cheap bounds visualization and detailed cell visualization. | Cells view is the one to use when diagnosing exact painted/baked coverage. |
#Named areas: hard restrictions vs soft preferences
Vaelis exposes 16 navigation-area slots. Name them with Edit → Nav Areas…, then use the names in script instead of memorizing bit positions.
#Hard restriction: Area Mask
var allowed = nav.areaMask("Ground", "Road");
var path = nav.findPath(this.x, this.y, 800, 300, {
area: allowed,
radius: 16
});An area omitted from the mask is impassable for that query. This is different from cost.
#Soft preference: Area Cost
var path = nav.findPath(this.x, this.y, 800, 300, {
area: nav.areaMask("Ground", "Road", "Mud"),
areaCosts: nav.areaCosts({
Road: 0.5,
Mud: 4
})
});Cost changes route preference among allowed areas. A cost of 1 is neutral; a higher value makes that area more expensive; a lower positive value makes it more attractive. Cost does not turn an allowed area into a hard wall.
areaCosts: { Water: 0 } to try to block water. Use nav.areaMask(...) and leave Water out of the mask.#NavAgent2D tuning: what every major value actually changes
| Field | Increase it | Decrease it | Use it when… |
|---|---|---|---|
radius | Agent needs wider clearance; narrow passages become unavailable sooner. | Agent can fit through tighter passages. | Different NPC sizes need to share the same NavWorld. |
speed | Higher top movement speed. | Slower movement. | Simple traversal pacing. |
acceleration | Reaches the requested speed faster. | Softer/slower speed changes. | Making movement feel snappy vs floaty. |
deceleration | Stops more quickly. | Longer, softer stopping. | Preventing overshoot near goals. |
stoppingDistance | Agent intentionally stops farther away. | Agent gets closer to target. | Enemies should keep melee/shooting distance. |
repathInterval | Fewer route checks; cheaper. | More frequent route checks; more responsive and more expensive. | Balancing moving-target responsiveness vs CPU work. |
repathDistance | Target must move farther before a re-path is triggered. | Target motion triggers re-path sooner. | Fast-moving targets. |
avoidancePriority | Higher priority means the agent is treated as more important in avoidance decisions. | Lower priority makes it more willing to yield. | Mixed-priority crowds or special NPCs. |
area | Add area bits to permit additional terrain categories. | Remove bits to forbid categories. | Making a route legally impossible through a terrain class. |
#Complete car / road navigation flow
Vehicle navigation is not simply “walk an NPC path with a car sprite.” Vaelis exposes this.navDriveToward() specifically for Car-type CharacterController movement and the NavAgent2D vehicle tuning fields.
Road. Use another area such as Ground for ordinary terrain.collabEnabled or avoidance only when you actually need those behaviors.nav.areaMask("Road") when the car must stay on roads. Use a wider mask if road-only routing is too restrictive.function onUpdate(dt) {
var target = findFirst("Destination");
if (!target) return;
this.navDriveToward(target.x, target.y, 220, {
repathInterval: 0.2,
arriveDist: 8,
finalArriveDist: 18,
debug: true
});
}For road-vs-ground preference, allow both and use costs instead of a hard mask:
var path = nav.findPath(this.x, this.y, target.x, target.y, {
area: nav.areaMask("Road", "Ground"),
areaCosts: nav.areaCosts({ Ground: 3, Road: 1 })
});#When to use Dynamic
Turn on Dynamic only when bake-relevant static geometry can actually change during play. The runtime checks a cheap collider signature and rebakes when the signature changes; it does not blindly rebake the entire world every frame. Dynamic navigation still has a real rebake cost when qualifying geometry changes.
// Procedural level example: after spawning a new static obstacle
var result = nav.bake();
if (result) debug.log("Nav rebuilt: " + result.walkable + " walkable, " + result.blocked + " blocked");#Navigation debugging checklist
2. Are the walls using Collider2D and eligible for baking?
3. Did you bake after editing static geometry?
4. Does Cells view show the corridor as walkable?
5. Is the agent radius too large for that corridor?
6. Is the Area Mask accidentally excluding the only available route?
7. Are you confusing area cost with a hard restriction?
8. Is your target inside the NavWorld bounds or at least near a walkable cell?
9. Is the script calling the correct method for the movement type (
navMoveToward vs navDriveToward)?10. Turn on
debug:true and make the debug overlay visible to inspect the actual route.#LLM/code-generation rule
When generating navigation code, preserve this dependency order: NavWorld2D → walkability/bake → named areas → NavAgent2D → script movement → tuning. Do not invent properties such as destination, setDestination, or a Unity/Godot class when Vaelis's documented API is this.navMoveToward(), nav.findPath(), and this.navAgent.*.