How to follow a moving target using NavigationAgent2D?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By zeruno

I am currently creating an enemy which will follow the player.

I was using the player GlobalPosition to calculate the direction of the enemy movement. I am now in the process of implementing obstacles in my map and I used a NavMesh and NavigationAgent to handle moving around obstacles.

When trying to update the navigation path each frame, the enemy seemed to move slightly left and right but ultimately getting stuck in the same position (see note below).

My question is: how should I handle updating the path towards the player? If I update the path per frame, the enemy does not seem to move towards the player (as just described), it might also imply performance issues, and if I take too long to update the path, the enemy moves towards a stale/outdated location.

PS. A tile map is being used to generate the NavMesh. In order to stop enemies getting stuck on corners, we are using this “solution” I noticed that when this “solution” is not used, updating the path per frame works as expected.

:bust_in_silhouette: Reply From: smix8

When you update the path to the target store the current position of the target. Then check on each update if the target has moved too far away from that position. If it has moved too far away query a new path, if not don’t query a new path.

If you query navigation paths every single frame it not only costs a lot of performance but it also might get agents stuck due to backtracking when the start position of the new path ends up slightly behind the agent’s current position. The pathfinding needs to search for the closest point on navigation mesh to your path query start and end positions which is not guaranteed to be “in front” of your agent which is just a position.

The linked “solution” is a cause for a lot of issues.

It pushes the navigation polygon merge from a solid and quick edge merge to the building edge connections over the gaps. This is slow in comparison when done for so many edges. Those edge connections are only virtual for the pathfinding so when an agents resets a path while being on that gap the pathfinding needs to find a start position on a “real” navigation polygon. If your distance checks on the NavigationAgent are set too small your agent might constantly be forced to reset the path in this situation.

The real solution would be to shrink the navigation polygon accordingly for the agent “size”. The tiled and small cell layout used by TileMap works directly against that. Use a NavigationRegion2D for navigation polygons if you want quality and performance even if it currently tedious to setup for TileMaps (which will be improved in properly Godot 4.1).