5

So my issues is that, for large groups of units, attempting to pathfind for all of them in the same frame is causing a pretty noticeable slow down. When pathing for 1 or 2 units the slow down is generally not noticeable but for many more than that, depending on the complexity of the path, it can get very slow.

While my A* could probably afford a bit of a tune up, I also know that another way to speed up the pathing is to just divy up the pathfinding over multiple game frames. Whats a good method to accomplish this?

I apologize if this is an obvious or easily searched question, I couldn't really think of how to put it into a searchable string of words.

More info: This is A* on a rectilinear grid, and programmed using C# and the XNA framework. I plan on having potentially up to 50-75 units in need of pathing.

Thanks.

  • What's your A* searching, a grid? Have you considered landmarking then using A* for "local searching"? – user7116 Jan 21 '12 at 00:25
  • I've never heard of this approach, but another way I just thought of to speed this up would be to lower the resolution of your grid so there aren't so many nodes to traverse before finding a path. You could refine the resolution and do some sort of iterative smoothing on the path while the entity is traversing it. – Merlyn Morgan-Graham Jan 21 '12 at 00:27
  • Six, could you be a little more specific please with what you mean by "landmarking", I'm a little new to path finding so I don't know all the jargon and such :). Merlyn thanks for the response but I don't think that will work well with the way my terrain is handled. – Marcos Alfonso Jan 21 '12 at 00:35
  • Basically you create a lower resolution version to find the high level path. You use the "landmarks", on a rectilinear grid this would be done like Merlyn suggested, to plan the high level path. Then when each unit makes it onto a "landmark", you use the low level grid to A* search into the next "landmark" along the way. I've done a bit of this in the past and spent a lot of time [reading up on Recast and Detour for help](http://digestingduck.blogspot.com/). – user7116 Jan 21 '12 at 00:45
  • If you can find them, there are lots of articles about A* techniques in the Game Programming Gems series of books, first one came out in 2000, volume 8 in 2010. – Roger Halliburton Jan 21 '12 at 01:24

2 Answers2

4

Scalability

There's several ways of optimizing for this situation. For one, you may not have to split up into multiple game frames. To some extent it seems scalability is the issue. 100 units is at least 100 times more expensive than 1 unit.

So, how can we make pathing more optimized for scalability? Well, that does depend on your game design. I'm going to (perhaps wrongly) assume a typical RTS scenario. Several groups of units, with each group being relatively close in proximity. The pathing solution for many units in close proximity will be rather similar. The units could request pathing from some kind of pathing solver. This pathing solver could keep a table of recent pathing requests and their solutions and avoid calculating the same output from the same input multiple times. This is called memoization.

Another addition to this could involve making a hierarchy out of your grid or graph. Solve on the simpler graph first, then switch to a more detailed graph. Multiple units could use the same low-resolution path, taking advantage of memoization, but each calculate their own high-resolution path individually if the high-resolution paths are too numerous to reasonably memoize.

Multi-Frame Calculations

As for trying to split the calculations among frames, there are a few approaches I can think of off hand.

If you want to take the multi-threaded route, you could use a worker-thread-pooling model. Each time a unit requests a path, it is queued for a solution. When a worker-thread is free, it is assigned a task to solve. When the thread solves the task, you could either have a callback to inform the unit or you could have the unit query if the task is complete in some manner, most likely queried each frame.

If there are no dynamic obstacles or they are handled separately, you can have a constant state that the path solver uses. If not, then there will be a non-negligible amount of complexity and perhaps even overheard with having these threads lock mutable game state information. Paths could be rendered invalid from one frame to the next and require re-validation each frame. Multi-threading may end up being a pointless extra-overhead where, due to locking and synchronization, threads rarely run parallel. It's just a possibility.

Alternatively, you could design your path finding algorithms to run in discrete steps. After n number of steps, check the amount of time elapsed since the start of the algorithm. If it exceeds a certain amount of time, the pathing algorithm saves its progress and returns. The calling code could then check if the algorithm completed or not. On the next frame, resume the pathing algorithm from where it was. Repeat until solved.

Even with the single-threaded, voluntary approach to solving paths, if changes in game state affect the validity of a paths from frame to frame, you're going to run into having to re-validate current solutions on a frame to frame basis.

Use Partial Solutions

With either of the above approaches, you could run into the issue of units commanded to go somewhere idling for multiple frames before having a complete pathing solution. This may be acceptable and practically undetectable under typical circumstances. If it isn't, you could attempt to use the incomplete solution as is. If each incomplete solution differs too greatly, units will behave rather indecisively however. In practice, this "indecisiveness" may also not happen often enough to cause concern.

Sion Sheevok
  • 4,057
  • 2
  • 21
  • 37
0

If your units are all pathing to the same destination, this answer may be applicable, otherwise, it'll just be food for thought.

I use a breadth-first distance algorithm to path units. Start at your destination and mark the distance from it as 0. Any adjacent cells are 1, cells adjacent to those are 2, etc. Do not path through obstacles, and path the entire board. Usually O(A) time complexity where A is the boards area.

Then, whenever you want to determine which direction a unit needs to go, you simply find the square with the minimal distance to the destination. O(1) time complexity.

I'll use this pathing algorithm for tower defense games quite often because its time complexity is entirely dependent on the size of the board (usually fairly small in TD games) rather than the number of units (usually fairly large). It allows the player to define their own path (a nice feature), and I only need to run it once a round because of the nature of the game.

CGravelle
  • 21
  • 1
  • 6