Navigation¶
Surface Flow Field is the optional route-authority system for levels with walls, islands, or uneven walkable surfaces.
When to use it¶
Massive Swarm System works without a flow field for flat arenas. Behavior steering, body blocking, and obstacle blocking keep agents moving toward the target and clear of walls in simple geometry.
Use the Surface Flow Field when:
- Agents need to route around walls, pillars, or closed rooms.
- The level has stairs, ramps, or uneven terrain that steering alone cannot handle.
- Agents get persistently stuck at corners or thin corridors.
Do not use it when:
- The level is an open flat arena with no routing obstacles.
- You need the lowest possible runtime overhead for very large agent counts.
How it works¶
The Surface Flow Field bakes a grid over the scene. Each cell stores a direction toward the swarm target. At runtime, agents sample their cell and blend the field direction with their behavior steering.
Bake cost scales with grid cell count, not agent count. Once the map is baked, per-agent cost is a single cell lookup.
Footprint and overhead clearance¶
The bake can reason about the agent's size so cells map cleanly around walls, gaps, and overhead obstacles. Two settings on SwarmManager drive it. Both are bake-time only and add no runtime cost.
- Clearance Radius (footprint width). The ground probe is a sphere of this radius. A gap between two walls narrower than twice the radius bakes as non-passable, while a doorway wider than the footprint stays walkable. Closely-spaced raised blocks separated by sub-footprint gaps bake as one continuous top surface the agent bridges, instead of an alternating top/floor row.
- Agent Height (standing height). With a non-zero height and an Unwalkable Layer Mask set, each cell checks a capsule of Clearance Radius spanning Agent Height above the floor. A floor under an overhead obstacle — a door lintel, a low arch, an overhang — bakes walkable when the agent fits under it and blocked when the obstacle is too low. Door jambs and full-height walls still block.
This requires floors and obstacles on separate layers: floors in Walkable Layer Mask, walls/overhead in Unwalkable Layer Mask. The bake samples the union of those two masks; there is no separate surface include mask to maintain. If the two masks overlap or Walkable is empty, the inspector warns and overhead detection turns off. Setting Clearance Radius to 0 reproduces the legacy single-ray point-sample bake.
Single surface per cell
The field is a height map: each XZ cell stores exactly one walkable height. Two consequences to plan around:
- Walking under an overhead obstacle is supported (one floor, obstacle above it). Two stacked walkable floors in the same column are not — a catwalk crossing over open floor bakes as only one of the two (the higher one the agent fits on).
- The bake takes the topmost walkable surface the agent fits on. If that surface fails the height check, the cell is blocked; it does not retry a lower walkable surface in the same column.
Setup¶
Disabled by default
Surface Flow Field Navigation is off in the default SwarmSettings. Agents use behavior steering and obstacle blocking until you enable it.
- In
SwarmSettings, enable Surface Flow Field Navigation. - On
SwarmManager, configure the bounds source: - Renderers — the manager fits bounds automatically from scene renderers under the bounds root.
- Colliders — the manager fits bounds automatically from scene colliders under the bounds root. Useful when ground/blocker geometry has colliders but no renderers, or when collider extents differ from renderer bounds.
- Custom — set explicit world-space center and size on
SwarmManager. - Set the bake layers on
SwarmManager: - Walkable Layer Mask — the floor/ground the bake stands agents on. Put your floors and ramps here.
- Unwalkable Layer Mask — walls, columns, overhead bars, and props that block. Keep this separate from Walkable.
- Enter Play mode. The manager bakes the map at startup.
Key settings¶
Surface Flow settings live in two places: bake-time grid configuration on SwarmManager, runtime routing parameters on SwarmSettings.
On SwarmManager¶
| Field | What it does |
|---|---|
| Surface Flow Cell Size | Grid resolution in world units. Smaller cells route more precisely but cost more to bake and store. |
| Walkable Layer Mask | The floor/ground layers the ground probe lands on. The down-cast targets these layers only, so it passes through an overhead obstacle (door lintel, low arch) and resolves the floor beneath it. Leave empty to fall back to the combined Walkable + Unwalkable mask (legacy point-sample behavior, no overhead handling). |
| Unwalkable Layer Mask | Obstacle layers (walls, columns, overhead bars, props). The lateral wall test and the standing-clearance check query this mask. Must stay separate from Walkable Layer Mask. |
| Clearance Radius | Agent footprint radius the bake reasons about, in world units. The bake sphere-casts at this radius, so a gap narrower than the footprint reads as solid ground the agent bridges, while a wider opening stays walkable. A slot between two walls narrower than twice this radius bakes non-passable. 0 = legacy single-ray point sample. |
| Agent Height | Agent standing height the bake reasons about, in world units. With a non-zero height and an Unwalkable mask set, each cell checks a capsule spanning this height above the floor, so a floor under an overhead obstacle bakes walkable only when the agent fits under it. 0 = footprint-only (no overhead detection). |
| Surface Flow Quality | Cardinal stores 8-way direction arrows. Smooth stores an integration field for wall-aware gradient sampling — more accurate around walls and corners. |
On SwarmSettings¶
| Field | What it does |
|---|---|
| Surface Flow Target Mode | How targets map to goal fields. Per Swarm Target bakes a separate field per active target slot. Nearest Swarm Target bakes one multi-source field toward all active targets simultaneously. |
| Surface Flow Authority | How strongly the flow field overrides behavior steering. 1 means the field fully controls direction; lower values blend with behavior steering. |
| Surface Flow Goal Release Distance | Agents inside this distance from their target ignore the flow field and use behavior steering directly. |
| Enforce Cell Boundaries | Prevents agents from crossing into cells the bake marked as blocked. Recommended on. |
Fallback behavior¶
When an agent is off the grid, in an unwalkable cell, or has no baked field:
| Fallback mode | What happens |
|---|---|
| Keep Behavior Steering (default) | Agent uses behavior steering without flow field influence. |
| Stop | Agent stops moving. |
| Use Last Flow Direction | Agent reuses the last valid flow direction. |
Grounding with the flow field¶
The field stores the ground height at each baked cell. When Surface Flow Grounding Mode is Prefer Field Height, agents on the field lerp their Y position to the cell's baked height. This replaces or supplements physics grounding for agents on the walkable surface.
Prefer Field Height— uses field height for agents on the field; falls back to physics grounding for off-field agents.Replace Physics When Available— uses field height for agents on the field; off-field agents always use gravity regardless of theEnable Groundingsetting.Disabled— flow field does not control Y. Physics grounding runs independently.
Runtime rebake¶
Surface Flow Runtime Rebake is enabled by default in SwarmSettings so goal fields rebake automatically as targets move. The bake is throttled by Rebake Interval and only triggers when the target moves past Goal Move Rebake Distance.
Background thread baking (the default) keeps bakes off the simulation thread and falls back to Main Thread automatically on WebGL. V1 ships no Jobs/Burst scheduler.
Congestion bias¶
When dense crowds funnel through a single corridor, a flow field alone tends to single-file every agent through the lowest-cost cell. Enable Congestion Bias in SwarmSettings to spread that traffic across parallel routes.
How it works:
- Each fixed step the manager counts how many agents currently sit in each surface-flow cell.
- When an agent samples its next direction, candidate neighbor cells that are already occupied are scored as less attractive — but never blocked.
- An agent will only divert if another route is also valid (lower-cost). In a one-cell-wide corridor it still walks straight through.
Settings:
| Field | What it does |
|---|---|
| Enable Congestion Bias | Master toggle. Off by default. |
| Strength | 0 disables the penalty. 1 strongly prefers equally valid lower-occupancy cells. Default 0.65 reads as a noticeable but not overpowering bias. |
| Free Cell Capacity | How many agents can sit in a candidate cell before the soft penalty starts. Default 1 keeps single-occupancy cells neutral; raise it for crowds that should pack more tightly before re-routing. |
Requirements:
- Surface Flow Quality must be
Smoothon the SwarmManager.Cardinalquality skips the integration field this feature samples; the bias has no effect there and a one-time warning is logged at runtime. - Settings take effect immediately — no rebake or restart is needed when toggling the feature or adjusting Strength / Free Cell Capacity in Play mode.
When to use it:
- Dense crowds that pile up at chokepoints or single-file along corridors that have parallel alternatives.
- Bullet-heaven / survivor scenes where agents should spread out around the player rather than stack into one column.
When to skip it:
- Open arenas with no corridors — there is nothing to spread.
- Very low agent counts where a single-file route is acceptable and you want to save the per-step occupancy pass.
Congestion reroute¶
Experimental
Congestion Reroute is experimental. Tuning defaults and trigger heuristics may change in future updates, and it is not covered by the support promise.
Where Congestion Bias nudges an agent's sampled direction at runtime, Congestion Reroute rebakes the surface flow itself. When a corridor stays crowded, the next bake charges those cells extra Dijkstra cost and the new field routes agents through alternative corridors.
How it works:
- Each fixed step the manager counts occupancy per surface-flow cell (the same data Congestion Bias reads).
- Agents moving slower than Stuck Speed count as more than one toward occupancy, so a single-file queue still trips the trigger even when no two agents share a cell.
- When total congestion weight across the map is at or above Trigger Crowding, the manager schedules one extra goal-field rebake for that target — at most once per Interval seconds.
- The rebake runs on the background bake scheduler. While it is in flight, agents keep following the previous field with no stall.
Settings (under SwarmSettings → Congestion Reroute):
| Field | Default | What it does |
|---|---|---|
| Enable Congestion Reroute | Off | Master toggle. |
| Interval | 2.0 s |
Minimum seconds between rebakes per target. Smaller values respond faster but burn more CPU on Dijkstra rebakes. Recommended 1.5–3.0. |
| Cost Scale | 4.0 |
How heavily congested cells weigh the Dijkstra cost. 0 disables the penalty. 1 means one extra agent costs as much as one extra horizontal step. Tight bottlenecks where agents can only stack 1–2 per cell often need 4–8 to overcome the extra length of the alternate route; wide bottlenecks reroute fine at 1–2. |
| Trigger Crowding | 2 |
Minimum total congestion weight before a rebake is scheduled. Lower values react faster to small pile-ups; raise it to avoid rebakes from transient crowding. With cell size ≈ agent diameter, keep this at 1–3. |
| Stuck Speed | 1.0 units/sec |
Agents below this speed count as 2 toward occupancy; faster agents count as 1. 0 disables the bonus. Typical agent speed is 3–5 units/sec, so the default catches body-blocked queueing without flagging normal motion. |
The Free Cell Capacity setting from Congestion Bias is shared — it controls how many agents a cell can hold before either feature treats it as congested.
Requirements:
- Works at either Surface Flow Quality — Cardinal or Smooth — because it only modifies edge costs, not the integration field.
- Settings take effect immediately. Changes to Interval / Cost Scale / Trigger Crowding / Stuck Speed do not require a manual rebake.
- Per-target rebake state is cleared automatically when targets disconnect or the swarm is reset.
When to use it:
- Persistent bottlenecks where Congestion Bias alone cannot spread the crowd because no parallel route is visible to the local sampler.
- Levels with two or more roughly equal paths to the same target — the rebake will discover the alternative and divert traffic.
When to skip it:
- One-corridor levels with no alternative route. The rebake cost buys nothing because the field has no other path to find.
- Scenes where bake cost is already tight — every triggered rebake is a full goal-field bake.
Use both together for the best spread: the bias smooths distribution in the moment, the reroute commits the change to the field over a few seconds.
Performance guidance¶
- Bake cost scales with total grid cells. For a 50 × 50 unit scene at 1-unit cell size: 2500 cells.
- Use Cardinal quality and a coarser cell size for maximum throughput. Use Smooth when routing near corners matters.
- Keep Surface Flow Concurrent Bakes low (1–2) to avoid bake traffic spikes when multiple targets are moving simultaneously.
- Reduced and Cheap tier agents resample the field less frequently (configured by Surface Flow Reduced LOD Sample Interval and Cheap LOD Sample Interval in
SwarmSettings). Cached directions are reused between samples.
Simple Flow Field Follower¶
A sample component that moves any non-swarm GameObject along the baked surface flow field. Use it for player characters, companion bots, or any object you want to navigate the same field the swarm uses — without connecting it to the swarm simulation.
Add it via Component → Massive Swarm System → Samples → Simple Flow Field Follower.
The component requires the flow field to be baked before it does anything. It runs in Update and calls SurfaceFlowField.TrySample each frame to read the flow direction at its current world position, then moves along that direction at Move Speed.
| Field | What it controls |
|---|---|
| Flow Field | The SurfaceFlowField to follow. When not assigned and Auto Find Field is on, the component finds the first active SurfaceFlowField in the scene at startup |
| Auto Find Field | Automatically locates a SurfaceFlowField at Awake when Flow Field is empty |
| Move Speed | Horizontal movement speed in world units per second |
| Height Offset | World-unit offset above the sampled ground height |
| Height Follow Speed | How quickly the object lerps toward the sampled ground height. 0 snaps immediately |
| Face Flow Direction | Rotates the object to face the current flow direction each frame |
| Turn Speed | Maximum turn rate in degrees per second when Face Flow Direction is on |
| Stop When No Flow | Stops movement when the current cell has no direction, which typically means the object reached the goal or landed in an unreachable cell |
| Enforce Cell Boundaries | Prevents the object from crossing into cells the bake marked as blocked. Mirrors the containment pass the swarm uses. Recommended on |
| Radius | Body radius used to keep the object clear of blocked cell edges, in world units |
| Wall Margin | Extra clearance beyond Radius. Increase if the body still clips into walls |
Runtime API. The component calls SurfaceFlowField.TrySample for flow direction and height, TryWorldToCellIndex and IsCellWalkable for cell containment, and CanMove to test whether a given cell transition is permitted by the bake. You can call these methods directly from your own scripts to build a custom follower without the sample component.
Use this when you want a non-swarm object to share the same routing as the swarm. Do not use it when the object needs physics-driven movement or when the flow field is not active in the scene.