I use a lot of path finding in my Monogame project which is taking a toll on the framerate, because in the worst case finding a path can take 200ms. So I looked into using Tasks to spread path finding computation over multiple frames and maybe even compute them simultaneously.
This required me to rewrite the path finding system into a version that I suspect is slower, and which definitely should use more memory. However! When I got it to work, the path finding now takes at most 8ms, and the memory usage according to Visual Studio has fallen by ~100MB.
That's nice of course, but just in the interest of understanding what's going on, can someone explain why this is?
The changes I made from before to after was basically to remove static path finding data, so that each task can have its own copy, and then I stuffed the path finding calls into a lambda and fed it to the Tasks.
Before:
while (requestQueue.Count > 0)
{
PathRequest request = requestQueue.Dequeue();
List<Tile> path = AStar.FindPathList(map, request.origin, request.target);
if (path == null)
{
Debug.Warn("Unable to find path.");
}
else
{
path = AStar.SimplifyPath(path);
}
}
After:
while (requestQueue.Count > 0)
{
PathRequest request = requestQueue.Dequeue();
Task pathTask = Task.Run(() =>
{
List<Tile> path = AStar.FindPathList(map, request.origin, request.target);
if (path == null)
{
Debug.Warn("Unable to find path.");
}
else
{
path = AStar.SimplifyPath(path);
}
request.returnAction(path);
});
}
How I make requests:
Tile origin = map.tiles.Get(/* ... */));
Tile target = map.tiles.Get(/* ... */));
pathManager.MakePathRequest(ReturnAction, origin, target);
agent.isAwaitingPath = true;
void ReturnAction ( List<Tile> path )
{
agent.isAwaitingPath = false;
if (path == null)
agent.transform.WorldPosition = new Vector2(map.BorderSize * 4, map.BorderSize * 4);
else
agent.path = path;
}