Hi everyone!
I’ve recently started learning and experimenting with the Unity job system and i was trying to implement the A* Pathfinding using it.
I was thinking that using multithreading would greatly improve the performance by splitting paths calculations amoung different threads but when i tested it i noticed that i wasn’t getting any performance boost.
That’s the code i’m using to test it(it’s called in the update function on a MonoBehavior):
private void Pathfind(bool multithread)
{
PathfindingNode start = new PathfindingNode((Vector2)t_start.transform.position, grid);
PathfindingNode end = new PathfindingNode((Vector2)t_end.transform.position, grid);
NativeArray<JobHandle> handlers = new NativeArray<JobHandle>(loops, Allocator.TempJob);
AStar[] jobs = new AStar[loops];
float time = Time.realtimeSinceStartup;
if (multithread)
{
for (int i = 0; i < loops; i++)
{
AStar aStar = new AStar(start, end, navPoints, grid);
jobs[i] = aStar;
handlers[i] = aStar.Schedule();
}
JobHandle.CompleteAll(handlers);
}
else
{
AStar aStar = new AStar(start, end, navPoints, grid);
for (int i = 0; i < loops; i++)
aStar.Run();
}
Debug.Log(Time.realtimeSinceStartup - time);
handlers.Dispose();
}
and here’s the job(note that it’s not been optimized, it’s a raw implementation for now):
public struct AStar : IJob
{
[ReadOnly] public NativeArray<float2> navPoints;
//public NativeList<float2> path;
private PathfindingNode start;
private PathfindingNode end;
private CustomGrid grid;
public AStar(PathfindingNode start, PathfindingNode end, NativeArray<float2> navPoints, CustomGrid grid)
{
this.start = start;
this.end = end;
this.navPoints = navPoints;
this.grid = grid;
//path = new NativeList<float2>(Allocator.TempJob);
}
public void Execute()
{
FindPath(start, end);
}
///<summary>
/// Find the path between start point and end point.
///</summary>
public void FindPath(PathfindingNode start, PathfindingNode end)
{
// Compute distance from start node and target node.
PathfindingNode current = start;
current.g = 0;
current.h = start.GetDistance(end);
// Initialize search list.
NativeList<PathfindingNode> toSearch = new NativeList<PathfindingNode>(Allocator.Temp) {current};
NativeArray<PathfindingNode> processed = new NativeArray<PathfindingNode>(grid.width * grid.height, Allocator.Temp);
while (toSearch.Length > 0)
{
current = toSearch[0];
// Choose best node.
foreach (PathfindingNode node in toSearch)
if (node.f < current.f || (node.f == current.f && node.h < current.h))
current = node;
// If we've reached the end goal trace back and build path,
// otherwise keep adding processed path
if (current.Equals(end))
{
// Trace back the path
CalculatePath(current, processed);
break;
}
for(int i = 0; i< toSearch.Length; i++)
if(toSearch[i].index == current.index)
{
toSearch.RemoveAtSwapBack(i);
break;
}
processed[current.index] = current;
NativeArray<PathfindingNode> neighbours = current.GetNeighbors();
for (int i = 0; i < neighbours.Length; i++)
{
PathfindingNode neighbour = neighbours[i];
bool inSearch = toSearch.AsArray().Contains(neighbour);
// Check if this neighbour node has already been processed, if yes discard it,
// otherwise keep computing it.
if (!processed.Contains(neighbour) && navPoints.Contains(neighbour.nodeCell.center))
{
if (!inSearch)
{
neighbour.connection = current.index;
neighbour.g = current.g + current.GetDistance(neighbour);
neighbour.CalculateH(end);
toSearch.Add(neighbour);
}
}
}
}
}
// Trace back calculated path and build pathfinding result.
public void CalculatePath(PathfindingNode start, NativeArray<PathfindingNode> pathList)
{
int iter = 0;
PathfindingNode currentPathNode = start;
NativeList<float2> path = new NativeList<float2>(Allocator.Temp);
while (currentPathNode.connection != -1 && iter < pathList.Length)
{
PathfindingNode cameFrom = pathList[currentPathNode.connection];
path.Add(cameFrom.nodeCell.center);
currentPathNode = cameFrom;
iter++;
}
pathList.Dispose();
path.Dispose();
}
}
I’m still new to the job system and i honestly don’t know what i might be doing wrong/breaking, so i would really appreciate if you let me know.
Thanks.