I’ve been setting up one way links between graphs that allow our enemies to leave their spawn areas to attack the player, but not navigate back into them once they are within the main area. Depending on exactly how things are set up sometime the enemies will refuse to find a path across the link.
I’ve managed to build a test case and isolate what is causing the bug (spoiler, it is in floodfill), but I’m not sure what the correct fix is.
If I set up three graphs (I used recast graphs but the bug should show up regardless of graph type) as shown below:
Graph 0,1 and 2 are in that order in the inspector, and each has that number as its graphIndex at runtime.
Graph 0 is the main play area graph, graphs 1 and 2 are the spawn areas.
There are a pair of one directional NodeLinks, one connects graph 1 to graph 0, the other connects graph 2 to graph 0.
There is a seeker that tries to create an ABPath from the green sphere (representing the spawn point) to the red sphere (representing the player)
If I drag the spheres around the scene to try different paths what I observe is:
- Pathfinding entirely within any one graph works.
- Pathfinding from graph 0 to either of the other graphs correctly fails to find a path
(since the links are one way) - Pathfinding from graph 2 to graph 0 correctly finds a path via the link
- Pathfinding from graph 1 to graph 0 INCORRECTLY fails to find a path via the link.
In the last case stepping through the seeker code reveals that it bails out early because the nearest node to the start point (in graph 1) and the nearest node to the end point (in graph 0) have different area IDs. The ABPath uses this as a heuristic to tell it that there isn’t going to be a valid path between the nodes.
Stepping through the Floodfill code reveals why the graphs end up as different areas. The following sequence of events occurs:
- FloodFill() steps through the three graphs in order
- graph 0 is flood filled, and all nodes are assigned to area 1
- Graph 1 is flood filled, assigning all nodes to area 2
- The link from 1 to 0 is followed, all of the nodes in graph 0 are re-flood filled and changed to area 2 (The link between graph 0 and graph 2 isn’t followed because it is one way)
- Graph 2 is flood filled assigning all nodes to area 3
- The link from 2 to 0 is followed, all of the nodes in graph 0 are re-flood filled and changed to area 3 (The link between graph 0 and graph 1 isn’t followed because it is one way)
Graph 1 ends up with all of its nodes coloured as area 2, and graphs 0 and 2 end up with nodes coloured as area 3.
Thus when one-way links are used to connect areas whichever is the last area to be flood filled will end up ‘winning’ and all of the other areas will end up with unique area ids, and will be early rejected when trying to path-find between them via the links.
I’m not sure what the correct long term fix is. I can probably work around it in my specific case by creating links that are bi-directional, but have a VERY high cost to traverse in the return direction.