Godot 4.0 Navigation Agent

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

Hi, I was wondering how to use the navigation agent. (Godot 4.0 alpha 7)

set_target_location ( Vector2 location ) is how the target location is done. But how is starting location handled.

get_nav_path ( ) keeps giving me an empty array.

I have a tile map with navigation and collision.

The documentation is not being very helpful here. It says:-
The agent needs navigation data to work correctly. NavigationAgent2D is physics safe.
navigation data means what. I thought the tile map with navigation tiles counted as navigation data.

:bust_in_silhouette: Reply From: cm

The starting position is the agent’s parent position. Also get_nav_path is empty because it is computed asynchronously. Wait for the path_changed signal, after which get_nav_path() should give a valid result.

I built a minimum example to test this. My hierarchy looks like this:

  • nav_test (Node2D)
    • tile_map (TileMap)
    • player (Sprite2D)
      • agent (NavigationAgent2D)
    • goal (Position2D)

And the script attached to nav_test:

extends Node2D

@onready var agent: NavigationAgent2D = $player/agent
@onready var goal: Position2D = $goal
@onready var player = $player


func _ready() -> void:
	agent.velocity_computed.connect(on_velocity_computed)
	agent.path_changed.connect(on_path_changed)
	agent.target_reached.connect(on_target_reached)
	agent.set_target_location(goal.global_position)


func _physics_process(delta: float) -> void:
	var next_location = agent.get_next_location()
	var v = (next_location - player.global_position).normalized()
	agent.set_velocity(v)


func on_velocity_computed(safe_velocity: Vector2) -> void:
	player.position += safe_velocity


func on_path_changed() -> void:
	print(agent.get_nav_path())


func on_target_reached() -> void:
	print("reached goal")
	get_tree().quit()

Thank you! I will test it out. And let you know.

Skydome | 2022-05-13 18:23

And btw how is collision avoidance handled with navigation agent? It says automatic but right now it gets stuck in walls.

Skydome | 2022-05-14 11:22

You need to define where it’s safe for an agent to travel. You can do this by adding NavigationRegion2D nodes and drawing paths, or by using a TileMap with navigation shapes defined on the tiles.

In either case you draw the paths where there is open floor, though be sure to leave a large enough gap between the walls and floor to account for the agent’s size.

cm | 2022-05-15 13:43

Thank you again!
I am going to work with the answer you gave to my other question.
Dynamic obstacle avoidance is what I would like to do. Avoid NPCs that are not the target.

Skydome | 2022-05-15 20:55

To make a dynamic obstacle you would add a NavigationObstacle2D node as a child to an object (npc, moving hazard, etc).

As long as you use the “safe” velocity from thevelocity_computed signal everything should work as expected.

cm | 2022-05-15 21:09