Moving/colliding multiple objects on a Nav2D/Tilemap

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

Hello everyone! I’ve been playing aroud with Godot a lot for the past few month and I am liking it a lot. However, I am having some difficulties with my current project and I feel it is time for me to seek advice from people with more experience, so here I am :slight_smile:

First of all, a simplified version of my project:

It’s a tilemap, the player spawns on a random tile and you can move within a mesh provided by tiles, nothing special. If you press T, a multiple instances of AI handled parties are added, all they do is roam the map randomly (you can use mouse wheel to zoom in and out for convenience). I am sure many of you will find the code below familiar, this is what I am currenlty using:

func move_along_path(distance : float):
var start_point : = position
#if _target != null:
#	goto(_target.position)
for _i in range(_path.size()):
	var distance_to_next : = start_point.distance_to(_path[0])
	if distance <= distance_to_next and distance >= 0.0 and distance_to_next != 0:
		position = start_point.linear_interpolate(_path[0], distance / distance_to_next)
		break
	if _path.size() == 1 and distance >= distance_to_next:
		position = _path[0]
		_path.remove(0)
		set_process(false)
		path_complete()
		break
	distance -= distance_to_next
	start_point = _path[0]
	_path.remove(0)

There are few issues however:

  • The more parties I have on the map, the slower it gets, the perfomance is pretty bad. If it was an RTS game or an action, I’d want to be able to handle much bigger numbers of instances at the same time. Is this approch bad for such projects? Is there a better way to handle pathfinding and movement on a map if I don’t want unit’s path snap to tiles?

  • I need to add a follow function and I am not sure what would be the best way to do it. You can see 2 commented lines in the code that I was using for this (goto function communicates with nav2d node, gives it new destination and recieves new path) but I think asking for new path every frame is bad for performance. Would it be good enough if I added a 1-2sec cooldown?

  • The most frustrating for me and basically the reason I am posting all of this since I’ve spent much time trying to figure it out. If you run the game, press T and spend some time watching the map, all parties will just stop simultaneously for no apparrent reason :frowning: Have I messed something up, am I missing something? Since paths/movement is handled by _process function of each instance separately, I don’t really understand why all paths get resetted at the same time, but it looks like they do…

Any useful advice is greatly appreciated!

My own workarounds and observations in case they are useful for anybody:

  1. and 3) Using kinematicbody2d for parties and _physics_process instead of _process helped a lot. The freeze issue disappeared altogether, animations seem a bit smoother too. Instead of recalculating positions every frame manually I rely on move_and_slide and my map navigation currently looks like this:
func _physics_process(delta):
# If party is not active, don't move
if is_active:
	# If there is a target to follow, compare final destination to target position every few seconds
	# and adjust path if needed
	if target != null:
		follow_cd += delta
		if follow_cd >= 1.0:
			goto(target.position)
			follow_cd = 0
	# Movement along path
	if path.size() > 0:
		var current_speed = speed * speed_modifier
		velocity = (path[0] - position).normalized() * current_speed
		if (path[0] - position).length() > 4:
			move_and_slide(velocity)
		else:
			position = path[0]
			path.remove(0)
			if path.size() == 0:
				path_complete()
  1. As for the follow function, I’ve decided to give a one second cooldown idea a try, it’s in the code above as well. I am not very happy with the delay and still thinking if there is a better way to go about it but it works overall and does not seem to impact game perfomance too much.

WannabeGamedev | 2019-02-28 00:23