- Home /
Script causes FPS Drops!
Hi, my A*pathfinding script causes hard FPS Drops. There is a huge bump in the graph in the profiler, which is because of this script:
void PathProcess()
{
foreach (Enemy enemy in enemies)
{
if(FindPath(enemy.transform.position, player.transform.position) != null)
{
enemy.path = FindPath(enemy.transform.position, player.transform.position);
}
}
}
public List<Node> FindPath(Vector3 startPos, Vector3 targetPos)
{
grid = gameObject.GetComponent<PathfindingGrid>();
Node startNode = grid.NodeFromWorldPoint(startPos);
Node targetNode = grid.NodeFromWorldPoint(targetPos);
List<Node> openNodes = new List<Node>();
HashSet<Node> closedNodes = new HashSet<Node>();
openNodes.Add(startNode);
while (openNodes.Count > 0)
{
Node currentNode = openNodes[0];
for (int i = 1; i < openNodes.Count; i++)
{
if(openNodes[i].fCost < currentNode.fCost | openNodes[i].fCost == currentNode.fCost && openNodes[i].hCost < currentNode.hCost)
{
currentNode = openNodes[i];
}
}
openNodes.Remove(currentNode);
closedNodes.Add(currentNode);
if(currentNode == targetNode)
{
return RetracePath(startNode, targetNode);
}
foreach(Node neighbour in grid.GetNeighbours(currentNode))
{
if (!neighbour.walkable | closedNodes.Contains(neighbour))
{
continue;
}
int newMovementCostToNeighbour = currentNode.gCost + GetDistance(currentNode, neighbour);
if(newMovementCostToNeighbour < neighbour.gCost || !openNodes.Contains(neighbour))
{
neighbour.gCost = newMovementCostToNeighbour;
neighbour.hCost = GetDistance(neighbour, targetNode);
neighbour.parent = currentNode;
if (!openNodes.Contains(neighbour))
{
openNodes.Add(neighbour);
}
}
}
}
return RetracePath(startNode, targetNode);
}
List<Node> RetracePath(Node startNode, Node endNode)
{
path = new List<Node>();
Node currentNode = endNode;
while(currentNode != startNode)
{
path.Add(currentNode);
if(currentNode.parent != null)
{
currentNode = currentNode.parent;
}
else
{
break;
}
}
path.Reverse();
grid.path = path;
return path;
}
int GetDistance(Node a, Node b)
{
int distX = Mathf.Abs(a.gridX - b.gridX);
int distY = Mathf.Abs(a.gridY - b.gridY);
if (distX > distY)
{
return 14 * distY + 10 * (distX - distY);
}
else
{
return 14 * distX + 10 * (distY - distX);
}
}
I use InvokeRepeating("PathProcess", 0.5f, 0.2f) in the Awake Method. The maximum amount of enemies i am spawning is 50. It would be so nice if you could find my problem... Thank You very much!
There are a few things, I mean you find path check if it is not null, then you find path again to assign it to enemy, thats 2 times you try to find a path. I can already guess thats not the best performance there, then there will probably also be a bit inside the findpath aswel that could be more optimized.
Answer by IvovdMarel · Jun 13, 2020 at 08:17 PM
1) To best find out what's causing the delays, you should use the 'Deep Profile' option. Very often you'll be surprised what's causing it (e.g. you might have something logging to the Console, generally drastically reducing your FPS)
2) As ShadyProductions mentions the algorithm could be optimized. Storing the FindPath result in a variable will make your algorithm twice as fast, and rather than creating two Lists for open and closed nodes, this could just be a property on the node itself that you set,
Thank you for your answer... the deep-profiler shows that there is a huge cpu-usage by CouroutonesDelayedCalls (the PathProcessFunction)... I think its because of the InvokeRepeating.
If i use the update method ins$$anonymous$$d... its the same. I also optimized the script a bit, but i only get 5 FPS more. :( But thank you for your Tips
I dont know how to change the two List into properties, beacuse i have to interate through all open nodes... and this is not possible with the node propery.