Keep a path up to date as the map changes with OnePath’s incremental replanner, and route many units to one goal with a single flow field.
using RecursiveAI.OnePath; var yard = new Grid(16, 8); using GridReplanner replanner = yard.CreateReplanner(new Cell(0, 0), new Cell(15, 0)); GridPath first = replanner.Replan(); Console.WriteLine($"open yard: cost {first.Cost:F4}, {first.Cells.Length} cells"); yard.SetRect(7, 0, 1, 7, AreaCosts.Wall); // a wall appears, open only at the bottom row GridPath detour = replanner.Replan(); Console.WriteLine($"after wall: cost {detour.Cost:F4}, {detour.Cells.Length} cells"); replanner.MoveStart(new Cell(4, 5)); // the unit has moved along GridPath onward = replanner.Replan(); Console.WriteLine($"moved start: cost {onward.Cost:F4}, {onward.Cells.Length} cells"); // One flow field serves every unit heading for the same goal. using GridFlowField toGoal = yard.CreateFlowField(new Cell(15, 0)); foreach (var unit in new[] { new Cell(0, 0), new Cell(3, 6), new Cell(12, 2) }) { toGoal.TryGetNext(unit, out Cell next); Console.WriteLine($"unit at ({unit.X},{unit.Y}): cost to goal {toGoal.GetCost(unit):F4}, next step ({next.X},{next.Y})"); }
open yard: cost 15.0000, 16 cells after wall: cost 21.3848, 17 cells moved start: cost 14.7279, 12 cells unit at (0,0): cost to goal 21.3848, next step (0,1) unit at (3,6): cost to goal 15.3137, next step (4,6) unit at (12,2): cost to goal 3.8284, next step (13,1)
The replanner
grid.CreateReplanner(start, goal) keeps its search state between calls (D* Lite by default; LPA* is the other choice). After an edit to the grid, Replan() repairs only what the edit affected, instead of searching again from scratch. MoveStart follows the unit as it walks, and the next Replan() reuses everything still valid.
The flow field
grid.CreateFlowField(goal) computes the least cost to the goal from every cell once. Each unit then asks two cheap questions: GetCost(cell) and TryGetNext(cell, out next), the step to take. Hundreds of units heading for one rally point cost one field.
Good to know
- Both are
IDisposable; dispose them when the unit or the goal goes away. - Both hear about edits to the grid they came from and repair only the affected region.
- Their state saves to bytes and restores exactly, like grids and searches; see saved search state.