Documentation

Paths, running and vertical movement

Understand reachable fallbacks, multi-tile units, ramps, stacked surfaces and tick-to-frame presentation.

On this page

Goal#

Extend your working flat scene with running, a 2×2 unit, a ramp and a second walkable level.

Before you begin#

Complete grid and character setup. Keep a copy of the flat scene for comparison, and check that your installed package contains the layered APIs described here.

Exact steps: pathfinding and running#

  1. Keep the TilePathService assigned to MovementMotor.pathServiceBehaviour. Current source uses A* with maxIterations = 3000, turn preference and closest-reachable fallback enabled.
  2. For custom path consumers, inspect PathResult.Success, ReachedExactDestination and ErrorMessage. TryMoveTo can accept a reachable fallback; TryMoveToExact requires the chosen destination.
  3. Call MovementMotor.SetRunning(true) from your own control or use the imported demo's supported UI. Compare walking with running: walking consumes at most one step per tick, running at most two.
  4. Add UnitFootprint and set footprintType to TwoByTwo. Compare a narrow corridor with an open area. The visual is offset by half a tile in X/Z to center it on the footprint. Supported enum values are OneByOne and TwoByTwo; do not assume arbitrary dimensions.

Exact steps: slopes, steps and stacked surfaces#

  1. Add a gradual ramp and a raised platform with enabled, non-trigger colliders. Include their layer in Ground Mask; put separate obstacles in Blocked Mask.
  2. Inspect maxWalkableSlope and maxStepHeightBetweenAdjacentTiles on GridManager. Defaults are 45° and 0.75 world units. Keep the test ramp and each adjacent height change within those limits.
  3. For overlapping levels, leave enableLayeredSurfaces enabled. Set ground-query height and distance to encompass both surfaces. Leave enough overhead clearance for requiredHeadroom, which defaults to 1.8 world units.
  4. Click the upper surface, then the lower route, using PlayerInputController. Its NavigationNode target retains surface identity. A request made only with TileCoord can select a different surface at the same X/Z position.
  5. For an explicit connection, add GridTransitionLink and assign its entry and exit transforms on valid surfaces. Both bidirectional and enabledForPathfinding default to true. This adds a navigation connection; implement any ladder/elevator presentation separately.
  6. If you alter colliders at runtime, deliberately refresh discovered surfaces using GridManager.ClearSurfaceCache(). Cached ground queries can otherwise retain the old geometry.
  7. Repeat with the 2×2 unit. Current source checks the full footprint for authored-floor movement and legacy flat movement, but some general layered height changes use anchor checks. Validate your actual ramp and bridge geometry instead of assuming complete volume clearance.

Debug overlays#

  1. Add GridOverlayRenderer to a separate diagnostic object. Its required GridOverlaySettings, MeshFilter and MeshRenderer are added automatically.
  2. Assign the renderer's settings and a compatible baseMaterial. It uses GridManager.Instance; there is no serialized grid reference on this renderer.
  3. Enable GridOverlaySettings.isEnabled and use small tile bounds while inspecting. Defaults are −64 to 64 on each tile axis. Saved PlayerPrefs may override the initial visibility.
  4. For a UI toggle, assign GridOverlayToggleController.settings and rendererToRefresh, then call Toggle() or SetEnabled(). Use the component methods to bind your own debug controls; it does not poll G/H keys.
  5. Add PathDebugDrawer to the unit, bind its motor/brain if they are not found automatically, and enable Scene Gizmos. It displays the authoritative path/tile and visual queue. For hovered-tile diagnostics, enable GridManager.drawHoveredTile and assign debugCamera.

Tick timing and frame rate#

TickManager accumulates Time.deltaTime and advances all elapsed ticks through a loop. UnitViewMotor consumes frame delta for visual playback. Movement timing therefore follows simulation time rather than rendered frame count. Unity Physics queries are involved; this does not guarantee identical physics results across platforms or network lockstep determinism.

What you should see#

Reachable paths advance on ticks, running consumes up to two steps per tick, and the visible unit follows the grounded path. Valid ramps connect; excessive step heights, slopes or insufficient headroom reject routes. The debug view helps distinguish the logical path from visual interpolation.

If something goes wrong#

A TileCoord-only target can select the wrong bridge level. A character collider in the blocked mask can reject its own route. Stale caches can hide runtime collider changes. Use the diagnostic checklist before increasing traversal limits.

Next steps#

Review GridManager, MovementMotor and IPathService for your extension.