【Godot】Pathfinding with NavigationAgent2D - Enemy AI Tracking and Patrol

Created: 2025-12-08

Learn how to implement efficient and natural enemy AI tracking and patrol behavior using Godot Engine's NavigationAgent2D node.

Introduction: Why Game AI Needs Pathfinding

In game development, enemy character and NPC movement is an element that greatly influences the quality of player experience. When walls, obstacles, and intricate maps exist, AI needs to find the optimal path to its destination. This technology of "finding the optimal path" is pathfinding.

Godot Engine provides the NavigationAgent2D node to achieve this complex pathfinding processing simply and efficiently.

Key Concepts and NavigationAgent2D's Role

Godot's navigation system consists primarily of three elements:

ElementNode NameRole
Navigation MapNavigationServer2DServer managing the entire movable area.
Movable AreaNavigationRegion2DDefines the area on the map where AI can actually move.
Path AgentNavigationAgent2DRequests path calculation and controls parent node (AI character) movement.

Basic Setup

To make NavigationAgent2D work, you first need to define movable areas on the map.

  1. Place NavigationRegion2D: Add a NavigationRegion2D node to the scene tree.
  2. Create NavigationPolygon: In the NavigationRegion2D inspector, create a new NavigationPolygon resource and edit it to cover the movable parts of the map.
  3. Prepare AI Character: Add a NavigationAgent2D node as a child of the enemy AI's root node (e.g., CharacterBody2D).

Practical Example 1: Player Tracking by Enemy AI

Enemy AI tracking the player is the most basic use case of pathfinding.

Tracking Logic Implementation

# Enemy.gd (attached to CharacterBody2D)

extends CharacterBody2D

@export var speed = 200.0
@onready var navigation_agent = $NavigationAgent2D

var target_position = Vector2.ZERO

func _ready():
    navigation_agent.max_speed = speed

func set_target(new_target_position: Vector2):
    target_position = new_target_position
    navigation_agent.target_position = target_position

func _physics_process(delta):
    if navigation_agent.is_navigation_finished():
        velocity = Vector2.ZERO
        move_and_slide()
        return

    var next_path_position = navigation_agent.get_next_path_position()
    var direction = global_position.direction_to(next_path_position)

    velocity = direction * speed
    move_and_slide()

In this code, when you set a target with set_target(), NavigationAgent2D automatically calculates the path. In _physics_process, simply moving the character toward the position obtained from get_next_path_position() achieves movement that avoids obstacles.

Practical Example 2: Implementing Natural Patrol

Patrol behavior where enemy AI sequentially visits multiple points can also be easily implemented using NavigationAgent2D.

Patrol Logic Implementation

# PatrolEnemy.gd (attached to CharacterBody2D)

extends CharacterBody2D

@export var speed = 150.0
@onready var navigation_agent = $NavigationAgent2D

var patrol_points = [Vector2(100, 100), Vector2(500, 100), Vector2(500, 500), Vector2(100, 500)]
var current_point_index = 0

func _ready():
    navigation_agent.max_speed = speed
    _set_next_patrol_point()

func _set_next_patrol_point():
    var next_point = patrol_points[current_point_index]
    navigation_agent.target_position = next_point

func _physics_process(delta):
    if navigation_agent.is_navigation_finished():
        current_point_index = (current_point_index + 1) % patrol_points.size()
        _set_next_patrol_point()

    var next_path_position = navigation_agent.get_next_path_position()
    var direction = global_position.direction_to(next_path_position)

    velocity = direction * speed
    move_and_slide()

The key to this implementation is using navigation_agent.is_navigation_finished(). This method returns true when the agent judges it has reached the target point, enabling more accurate and reliable target arrival detection than manually calculating distance.

Implementation Best Practices

1. Controlling Path Recalculation Frequency

Every time you set navigation_agent.target_position, path recalculation occurs. For player-tracking AI, updating the target every frame could impact performance.

  • Using Timers: Use a timer node to update target position at fixed intervals like every 0.1 seconds.
  • Distance-Based Detection: Update target position only when the player moves beyond a certain distance.

2. Pursuing Smooth Movement

NavigationAgent2D tells you the next point on the path, but it's the developer's responsibility to move the character toward that point.

Rather than just moving toward the next point, gradually changing `velocity** creates smoother movement.

3. Utilizing get_next_path_position()

NavigationAgent2D calculates the complete path to the target point, but what the character should move toward is the next point on that path. get_next_path_position() returns the next point on the path closest to the character's current position.

Summary

Godot Engine's NavigationAgent2D is a powerful tool that dramatically simplifies AI movement logic in 2D games.

  • Define movable areas with NavigationRegion2D,
  • Set target position in NavigationAgent2D,
  • Move the character toward the next point obtained from get_next_path_position()

With this simple procedure, you can immediately integrate practical and natural AI into your game that smartly avoids obstacles, tracks players, or patrols designated routes.