Navigation2D + collision avoidance help

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

So I have managed to do pathfinding with navigation2d. But now I need to also do obstacle avoidance.



    func Navigate():
    	if path.size()>0:
    		#print("Navigate")
    		#Enemy_Character is the Enemy AI using the navigation
Enemy_Character.velocity=Enemy_Character.global_position.direction_to(path[1]) 
    		
    		if Enemy_Character.global_position==path[0]:
    			path.pop_front()
    	pass
    
    func generate_path():
    	if nav2d!=null and Target!=null:
    		#print("Generate Path")
    		path= nav2d.get_simple_path(Enemy_Character.global_position, Target.global_position, false)
    		
    		Enemy_Character.line2d.points=path
    	pass

So this navigation is working. But obstacles are not avoided. Obstacles like other enemy NPCs or magic barriers or ice barriers.

I have created 3 raycast 2ds to detect collision with other enemies and miscellaneous environment objects. But I don’t know what to do next. Like ok I detected the collision but now how do I generate a new path that avoids the collision.

I have looked at some obstacle avoidance. But they’re doing the navigation very differently. None of them use navigation 2d for starters. I have been working on a steering velocity. But it’s kind of not working.

Navigation and collision avoidance is a very new topic for me. .Any help would be appreciated.

:bust_in_silhouette: Reply From: bloqm

I’m trying to figure out this aswell. This is an incomplete and probably erroneous answer.
So far I’ve managed to pathfind using Navigation2DServer but I haven’t managed to add dynamic obstacles.

I believe you have to set up Navigation2DServer and then request the path from Navigation2DServer, not to your nav2d instance.

My setup includes calling Navigation2DServer with: map_create map_set_active region_create region_set_map region_set_navpoly region_set_transform and maybe some others that I’m missing – in other words you’ll be loading a lot of info from your scene onto Navigation2DServer.

After you have set up your map and regions you’d call:

path = Navigation2DServer.map_get_path(map, pos_a, pos_b, true)

You might also want to set up agents and obstacles. I think that agents are used to avoid each other on the fly, while obstacles are ‘markers’ that somehow work with Navigation2DServer.

Perhaps unrelated: this issue has some images of how it’s set up in Godot 4: 2DNavigation pathing around obstacles with safe_velocity creates inconsistent and poor/broken movement w/ wide turns · Issue #57967 · godotengine/godot · GitHub

I’m super interested in this, and there is little info on the topic. If you manage to make it work please let me know!

Follow up to this: I managed to set up the whole thing in Godot 3.5, but I was dissapointed.

It seems that the core functionality is unchanged – the navigation returns a path across all the obstacles, as if they were walkable… Collision avoidance only changes the speed and positioning of how that path is followed, sometimes moving into ‘solid’ areas or simply getting stuck in obstacles without finishing the path or trying to find a new viable one.
There is still no way to forbid navigation around obstacles, much less dynamic ones.

AStar is the way.

bloqm | 2022-05-11 17:27

Thank you for your answer.
Will AStar have automatic collision avoidance though? I talked to someone and AStar is also only for pathfinding. Obstacle avoidance will still have to be separate. I will try AStar and let you know.

Skydome | 2022-05-11 18:15

:bust_in_silhouette: Reply From: smix8

Avoidance works with velocities, not with pathfinding or paths.

If you want pathfinding or a path not going through an obstacle you need to remove that navigation mesh below the obstacle.

In Godot 3.5+ for avoidance you define an agent’s radius and position and send a wanted velocity to the NavigationServer. The server calculates a “safe” velocity considering all the other agents (obstacles are just simplified dummy agents). The NavigationAgent2D set_velocity() can be used to send the velocity and the velocity_computed signal can be connected to receive the “safe” velocity from the server.