Better way for pathfinding in top-down game

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

Hello, I’m doing a top-down shooter game currently and I recently started adding pathfinding, to make it more difficult for the enemies to be near their objective.

I started checking a template project about basic pathfinding, using Navigation2D and this what I got:

extends KinematicBody2D
var direction
var path: Array  = []
var speed = 40
onready var plr = get_tree().get_root().get_node("Level/Scene/Player/Player")
func createPath():
	path = get_tree().get_root().get_node("Level/Navigation2D").get_simple_path(global_position, plr.global_position, true)
	path[0] = global_position
	get_tree().get_root().get_node("Level/Line2D").points = path

func _ready():
	createPath()

func move():
	direction = move_and_slide(direction)

func navigate():
	if path.size() > 0:
		direction = global_position.direction_to(path[1]) * speed
		
		if global_position == path[0]:
			path.pop_front()

func _process(delta):
	createPath()
	navigate()
	move()

Of course, some parts of the codes were not copied exactly and were modified for the game purpose. The top-down shooter game consists of infinite rounds of enemies appearing each amount of seconds, and after testing this method I found the next things

  1. If I use createPath() in the process function, when I get further from enemies, the game fps starts to decrease

  2. If I use createPath() in a Timer that changes the path every one second, each second will stop and will start moving weird from left to right and after will continue until the timer stops again and creates a new path.

  3. It doesn’t do the exact path and sometimes tries to cross over walls. (In this case, I didn’t put cells where walls are, so the pathfinding system can interpret that cannot create a path over those parts, but for some reason, stills doing it. This happens, even more, when optimize option is enabled)

¿There’s a way to fix this or to do a more efficient pathfinding system that doesn’t sacrifice FPS when the player is far?

  1. i suppose that’s because it is adding more and more points to the path. that has to do more with the complexity of the navigation polygon rather than pathfinding. maybe reduce the max distance in which the enemies look for the player? or maybe make them follow a fictional point in the general direction of the player, but closer to them.
    Or, if nothing works, you can think about including the pathfinding in a secondary thread

  2. I think the way you constructed the method navigate works correctly only when the path is updated every frame. I dont know how the code for the timer version is, but:

  • If you left navigate in _process, it will call pop_back on the first frame, and from frame 2 (you are still very close to the original point[0]) the direction will point toward the original point[2], instead of the original point[1], therefore it will never reach global_position == path[0] again (because path[0] is the original point[1]) and will continue moving in the same direction until the timer clocks again
  • If you put navigate in the fuction called by the timer signal, the direction is updated only once a second, therefore you will see the enemies taking that direction and never changing it until the timer clocks again
  1. no clue, but maybe it has to do with overlapping polygons, since it seems you are using a tilemap

Andrea | 2021-08-25 11:44