Skip to main content

Rooms, Portals, and Navigation

Polygon Engine provides two independent, fixed-capacity world systems:

  • Rooms and Portals conservatively reject renderers outside the camera's potentially visible portal chain.
  • Navigation bakes height-aware grid samples and moves NavMesh Agent GameObjects along three-dimensional runtime paths.

Author both from View > Advanced Scene Authoring > Rooms & Navigation.

Rooms​

A Room is an axis-aligned volume centered on the GameObject Transform plus its authored offset.

PropertyMeaning
EnabledInclude the room in runtime queries
NameUnique scene-local label
SizeWidth, height, and depth of the volume
OffsetLocal offset from the room GameObject position
PriorityTie-breaker when volumes overlap; highest wins

Assign environment Mesh Renderers with Renderer Room. An unassigned renderer remains globally eligible for the normal visibility path.

At runtime, the camera room is the highest-priority enabled Room whose AABB contains the camera. The renderer remains eligible when it is global or its assigned room is retained by the runtime portal traversal.

Portals and Recursive Connectivity​

A Portal references Room A and Room B and stores an enabled/open state, opening width and height, and Two Sided flag. The PS1 runtime traverses the graph recursively:

  • A can reach B through every enabled open Portal;
  • B can reach A only when that Portal is Two Sided;
  • every valid opening directly adjacent to the camera room is retained;
  • later rooms are retained only when the incoming and outgoing conservative aperture cones overlap.

Each cone contains the complete authored rectangular opening. The test is deliberately broader than exact portal-plane clipping, so it can retain rooms that are not ultimately visible. Invalid graph references, missing or malformed portal transforms, an unknown camera room, a camera inside an opening, queue pressure, or other ambiguous data fail open instead of risking a missing room. Global and unknown room assignments also remain visible.

Editor Play Mode and the PS1 runtime share the same conservative aperture math, recursion limits and fail-open policy, so room eligibility matches for the same camera and scene state. Validate performance and final presentation in the packaged build. This system does not provide hardware occlusion queries, automatic room splitting, or automatic per-triangle room assignment.

Lua can change a Portal at runtime:

local doorPortal = -1

function Start(gameObjectId)
doorPortal = GameObject.Find("Door Portal")
end

function openDoor(gameObjectId)
Portal.SetOpen(doorPortal, true)
end

See the Portal Lua API.

Height-Aware Navigation Bake​

Add NavMesh Surface to a root GameObject. Its volume establishes an X/Z grid and a vertical sampling range. The surface may rotate around Y. The surface center Y remains a backward-compatible base floor, while explicit traversable box faces add or replace quantized layers. The bake creates deterministic four-neighbour links between compatible samples.

Surface propertyDefaultBake effect
Size / Offset8,4,8 / 0,0,0Bounds the sampled volume
Cell Size0.50X/Z grid resolution
Cell Height0.25Quantizes sampled heights
Agent Radius0.30Expands obstacle clearance
Agent Height1.80Rejects nodes without enough headroom
Max Step0.35Maximum normal neighbour height difference
Max Slope45 degreesRejects steeper walkable faces
Max Drop1.50Maximum authored one-way WalkOff descent

The bake can retain multiple Y samples at the same X/Z cell, allowing overlapping floors inside one surface volume. Increase the volume height and place explicit walkable geometry at each level.

Navigation Modifier classifies a Collider for the bake. Modifier geometry must be on a root GameObject.

AreaCollider ruleResult
ObstacleNon-trigger box or sphereBlocks covered navigation cells
WalkableSolid boxSamples the box's upper face as traversable geometry
PlatformSolid boxSame static bake behavior as Walkable; useful authoring label for platforms
WalkOffTrigger volumeAllows downward-only links from covered source cells

Walkable and Platform boxes may be rotated or sloped. The baker evaluates the actual transformed upper plane, its height, and its slope. Platform is a static bake classification; it does not add moving-platform velocity, rider parenting, or dynamic rebaking.

A WalkOff link is created only when the destination is lower by more than Max Step and no more than Max Drop. It has no reverse upward link. The trigger marks permission to drop; it does not simulate falling or replace gameplay collision.

Ordinary enabled non-trigger Colliders are obstacles unless an enabled Walkable/Platform modifier classifies them otherwise. Ordinary obstacle boxes support Y rotation for the navigation bake. The NavMesh Surface and ordinary obstacles remain root, yaw-only authoring paths; explicit Walkable/Platform box sampling is the supported rotated-slope path.

Use Preview Navigation Bake to inspect node and directed-link counts, warnings, and errors before building. Its top-down graph uses node color to represent height. The preset menu offers:

PresetCell Size / HeightAgent Radius / HeightMax Step / Slope / Drop
Balanced0.50 / 0.250.30 / 1.800.35 / 45 / 1.50
Tight Indoor0.25 / 0.1250.30 / 1.800.30 / 45 / 1.00
Large Outdoor1.00 / 0.500.45 / 2.000.50 / 42 / 2.00
Precision Platforming0.25 / 0.1250.25 / 1.600.20 / 40 / 4.00

Apply Preset changes the bake parameters but not the surface Size or Offset. Preview the result again after any geometry or parameter change, then validate the packaged runtime path on its intended scene.

A NavMesh Agent must be on a root GameObject and reference one surface.

PropertyMeaning
SpeedMaximum movement speed
AccelerationRate used to approach maximum speed
Stopping DistanceFinal waypoint tolerance
Rotate to VelocityTurn Y rotation toward X/Z movement

NavMeshAgent.SetDestination() finds a complete lowest-cost path with deterministic Dijkstra search. It can follow authored links to connected surfaces and advances the GameObject through three-dimensional baked waypoints. Requests above 32 path points fail rather than returning a misleading partial route. Acceleration zero applies full speed immediately. Check the boolean result of every request.

Navigation writes the root Transform. If another script moves an active agent, it recalculates the route from the new position against the existing bake, or stops if no complete route exists. It does not add Character Controller collision response, dynamic obstacle avoidance, or runtime geometry rebaking.

The bake is not an arbitrary triangle navmesh or Recast-style runtime system. See the NavMesh and NavMeshAgent Lua API.

First Navigable Scene​

  1. Create a root GameObject named Navigation Surface. In View > Advanced Scene Authoring > Rooms & Navigation, add NavMeshSurface and keep it enabled. Place its center Y at floor height.
  2. The initial Size is 8 by 4 by 8 units and Cell Size is 0.5. A single unobstructed layer uses 256 nodes, the scene limit. For additional surfaces or stacked floors, reduce Size or increase Cell Size before adding more nodes. Presets change cell settings, not volume size.
  3. Mark solid floor boxes with Navigation Modifier > Walkable. Ordinary solid wall boxes block navigation. Keep this authoring geometry at the scene root. The navigation graph comes from the volume and colliders, not from visual mesh triangles.
  4. Create a root GameObject for the agent. Put its origin at foot height near a sampled point, add NavMeshAgent, and assign the enabled surface. Put the visible model on a child if its origin is at its center. An enabled agent's own Collider is excluded from static obstacle baking.
  5. Click Preview Navigation Bake. Check that both the starting area and destination have nodes connected by links. Thin walls must separate routes; adjust Cell Size and Agent Radius to keep corridors usable.
  6. Attach a Lua Behaviour and use the movement example. Restart Play Mode after editing navigation geometry. Export again to update the graph used on PS1.

Add Navigation Link to a root GameObject to bridge a gap between samples or surfaces. Set Start Surface and End Surface when you need precise surface selection. The endpoint offsets use the link GameObject's local transform. Snap Distance limits how far each endpoint may project onto a node.

Enable Bidirectional for travel in both directions; otherwise only start to end is allowed. Cost Multiplier controls route preference. When several links connect the same nodes, the lowest cost is used. Preview reports endpoints that cannot snap or both snap to the same node.

The agent's assigned surface anchors the reachable network. Unconnected surfaces are not automatically merged. Traversal is straight movement along the authored segment: the link grants permission to cross it, so verify the clearance yourself. It does not automatically jump, animate a ladder, open a door, or wait for a lift.

SymptomCheck
An enabled agent references a disabled surfaceEnable both the surface GameObject and its component, or disable the agent
No walkable cellsMark a solid floor as Walkable; check floor height, blocking colliders, volume bounds, and agent clearance
Destination rejectedCheck endpoint height and distance from nodes, directed connectivity, and the 32-point path limit; use a small SamplePosition radius and check SetDestination
Route stops after a teleportThe new position cannot reach the existing goal; move onto a valid sample and request a new destination
Agent repeatedly restarts or barely acceleratesDo not request the same destination every frame or combine navigation with another movement controller
Scene changes are ignored during playThe graph is static; stop and restart Play Mode or export again after editing geometry

Limits​

ResourceLimit
Rooms24
Portals48
NavMesh Surfaces4
NavMesh Agents16
Baked nodes256
Baked directed links1,024
Path points per request32

Increase cell size, reduce sampled floors, or split the scene when the graph approaches node or link capacity.