A* Pathfinding Project
4.1.9
The A* Pathfinding Project for Unity 3D
|
Cooperative Pathfinding. More...
Cooperative Pathfinding.
Cooperative pathfinding is used to calculate paths for agents in such a way that collisions between the agents are minimized.
This is achieved by instead of searching only on a graph of nodes searches are done on (node,time) pairs (up until some fixed time into the future for performance). When an agent has calculated a path, it will reserve all nodes it will visit for exactly the times it will occupy that time. So a path going through nodes A, B and C will reserve A at time 0, B at time 1 and C at time 2. Since agents reserve whole nodes, cooperative pathfinding works best for grid graphs where the agents have roughly the same size as a single node. However it might be suitable to use point graphs for some games. Cooperative pathfinding works on navmesh based graphs, however it doesn't make that much sense since the nodes (triangles) in navmesh based graphs can vary a lot in size.
Since the agent needs to know exactly where it will be in the future, special movement scripts need to be used. The regular movement scripts only follows the paths, but they give have any guarantees that they will reach specific points at specific times. The CooperativeAI script can be used for this purpose. It will make sure that the agent reaches the correct nodes at the correct times. A limitation of cooperative pathfinding is that all units need to move at exactly the same speed of one node per tick. There are plans to extend this to work at multiples and simple fractions of the default speed (e.g 2, 3, 1/2, 1/3 times the tick).
If you are writing your own movement scripts, cooperative pathfinding also requires a special path type, the CooperativeABPath. It works as a drop in replacement for the regular ABPath, but it takes the cooperative pathfinding information into account.
You will also need to attach the CooperativeContext component to the same GameObject that has the AstarPath component. That component holds the reservation table mentioned above and has some additional options.
Classes | |
class | Agent |
class | CooperativeNNConstraint |
class | CooperativePathData |
struct | Entry |
(node,time) pair More... | |
interface | IAgent |
struct | Item |
struct | SearchChainElement |
Public Types | |
enum | Mode { ReduceCollisions, ReduceWaits } |
See #mode. More... | |
Public Member Functions | |
IAgent | AddAgent (Vector3 position) |
int | GetReservation (GraphNode node, int time) |
Returns the pathID which has reserved the specified node at the specified time. More... | |
Public Attributes | |
List< Agent > | agents = new List<Agent>() |
bool | prioritizeRightHandTraffic = true |
Choose a preferred side of narrow corridors to help resolve congestion faster. More... | |
int | softReservationPenalty = 1000 |
Penalty to use for soft reservations. More... | |
int | temporalDepth = 30 |
Maximum number of time steps to be used in path planning. More... | |
float | tickLength = 1 |
Length in seconds of each tick. More... | |
Properties | |
int | Tick [get] |
Current tick. More... | |
float | Time [get] |
Current tick with the fractional part. More... | |
Private Member Functions | |
void | AddAgent (Agent agent) |
List< Agent > | FindTrail (Dictionary< GraphNode, Agent > node2agent, Agent agent, out Agent blockingAgent, out bool isCycle) |
PathHandler IPathHandlerProvider. | GetNewPathHandler (int threadID, int totalThreadCount) |
Returns a new CooperativePathHandler. More... | |
void | Init () |
void | OnDrawGizmos () |
Draw nice visualizations for the reservation table. More... | |
void | OptimizePath (CooperativePathData path) |
void | PostPathCalculated () |
void | RemoveAgent (Agent agent) |
void | RemoveReservation (GraphNode node, int time, int pathID) |
Remove reservation for the node at the specified time if it is currently reserved by the pathID. More... | |
bool | RemoveReservation (CooperativePathData path) |
Remove reservations which were added with Reserve(CooperativeABPath) More... | |
bool | RemoveReservationInternal (CooperativePathData path) |
void | Reserve (GraphNode node, int time, int pathID, bool hard, bool fromEnd) |
Reserves the node at the specified time with a pathID. More... | |
void | Reserve (CooperativePathData path) |
Reserve all (node,time) pairs which the path will occupy. More... | |
List< SearchChainElement > | SearchForChain (Dictionary< GraphNode, Agent > node2agent, Agent agent, Agent firstAgentInOriginalChain, int maxCost) |
void | TickTime () |
Advance tick by one. More... | |
void | TryToMove (Dictionary< GraphNode, Agent > node2agent, Agent agent) |
void | Update () |
Increments tick every tickLength seconds. More... | |
Static Private Member Functions | |
static void | RemoveFromIndex< T > (List< T > ls, int index) |
Private Attributes | |
System.Object | lockObject = new System.Object() |
Provides thread synchronization. More... | |
Dictionary< GraphNode, Agent > | node2agent = new Dictionary<GraphNode, Agent>() |
List< Entry > [] | reservationDropList |
Cyclic queue of entries to be removed. More... | |
Dictionary< Entry, int > | reservations = new Dictionary<Entry, int>() |
Space-time reservation table. More... | |
System.Random | rnd = new System.Random() |
int | tick |
Current tick. More... | |
double | time |
Current tick, including fractional part. More... | |
|
strong |
|
private |
IAgent AddAgent | ( | Vector3 | position | ) |
|
private |
|
private |
Returns a new CooperativePathHandler.
Called by the AstarPath class during Awake.
Implements IPathHandlerProvider.
int GetReservation | ( | GraphNode | node, |
int | time | ||
) |
Returns the pathID which has reserved the specified node at the specified time.
Zero is returned if there is no reservation. A negative pathID is returned if it is just a soft reservation.
|
private |
|
private |
Draw nice visualizations for the reservation table.
|
private |
|
private |
|
private |
|
staticprivate |
|
private |
Remove reservation for the node at the specified time if it is currently reserved by the pathID.
|
private |
Remove reservations which were added with Reserve(CooperativeABPath)
|
private |
|
private |
Reserves the node at the specified time with a pathID.
node | Node to reserve |
time | Tick to reserve the node at (see Tick) |
pathID | Path which reserves this node |
hard | If false, only a penalty will be applied (see softReservationPenalty) |
|
private |
Reserve all (node,time) pairs which the path will occupy.
|
private |
|
private |
Advance tick by one.
|
private |
Increments tick every tickLength seconds.
|
private |
Provides thread synchronization.
bool prioritizeRightHandTraffic = true |
Choose a preferred side of narrow corridors to help resolve congestion faster.
In narrow corridors agents will be penalized for moving on the left side of the corridor. This will have the effect of agents being less likely to cross paths and thus congestion will usually be reduced. It has a slight performance impact.
This effect is present everywhere that there are walls, not just in corridors. However it is in corridors that it matters the most.
|
private |
Cyclic queue of entries to be removed.
When the time for an entry has passed it will be removed to avoid storing entires forever.
Space-time reservation table.
Each entry specifies the path ID which has reserved the specified node at the specified time
|
private |
int softReservationPenalty = 1000 |
Penalty to use for soft reservations.
Soft reservations are used when #mode = ReduceWaits and the agent is waiting or standing still. This will discourage other agents from using the same node at the same time, but it will not prevent the agent from doing that. This will reduce the times the agents get stuck waiting for a long time however it can lead to more collisions.
A penalty of 1000 is roughly equal to the cost of walking one world unit.
int temporalDepth = 30 |
Maximum number of time steps to be used in path planning.
A higher number increases both memory usage and the time to calculate a path. The memory usage increases linearly so a temporal depth of 20 will use roughly twice as much memory as a temporal depth of 10. Higher values will also make path searches slower.
Recommended values lie between 8 and 50 (very soft limits). A higher value will make the agents able to resolve more complicated situations however it may reduce the responsiveness of the agents and sometimes simpler situations will take longer to resolve. A lower value will make the agents more naive.
This value cannot be changed during runtime.
|
private |
Current tick.
float tickLength = 1 |
Length in seconds of each tick.
All units will move a single node per tick
|
private |
Current tick, including fractional part.
|
get |
|
get |
Current tick with the fractional part.