Navigation drops framerate significantly

Godot Version

4.2.1

Question

Hello everyone!
Long story short: I have a number of objects which spawn a unit with navigation mechanics (trader), and it suppose to go from object A to object B and then return back. Unfortunately I’ve faced a number of issues with the script at the moment:

  1. At the beginning of the movement Trader “jumps” instead of moving slowly from the initial position to the first point in the path
  2. At the moment of building the path, framerate drops to 10-5% of the initial quantity of fps.

I want to use this system for quite a large amount of units similar to this one, how can I improve the efficiency of navigation?

P.S. GameLogic.int_time is just a var from singleton to hold and count time of the day; GameLogic.cities are spawn\destination objects.

extends CharacterBody3D

var start_position
var finish_position
var next_position
#var position_title

var speed = 100

var is_active : bool
var is_reached_the_position : bool
var is_raided : bool

var map : RID
var path : PackedVector3Array

@onready var navigation_agent = $NavigationAgent3D

func _ready():
	call_deferred("setup_navigation_server")
	is_active = false
	is_reached_the_position = false
	is_raided = false
	start_position = global_position
	visible = false

func _process(delta):
	if GameLogic.int_time == 5 and !is_active :
		pick_target()
		set_rout()
	if GameLogic.int_time == 10 and !is_active:
		visible = true
		is_active = true
	if is_active:
		if(navigation_agent.is_target_reachable()):
			if navigation_agent.distance_to_target() > 0.2:
				var direction = (path[0] - global_transform.origin).normalized()
				velocity = direction * speed * delta
				move_and_slide()
				if global_position.distance_to(path[0]) <= 0.2 and path.size() > 1:
					path.remove_at(0)
				elif path.size() <= 1 and !is_reached_the_position:
					is_reached_the_position = true
					visible = false
					finish_position = start_position
					start_position = global_position
					await get_tree().create_timer(1.0).timeout
					visible = true
					set_rout()
				elif path.size() <= 1 and is_reached_the_position:
					is_reached_the_position = false
					visible = false
					is_active = false
					start_position = global_position

func setup_navigation_server():
	
	map = get_world_3d().get_navigation_map()
	
	await get_tree().physics_frame
	
	var optimize_path = true

func set_rout():
	var start_position: Vector3 = global_position
	var target_position: Vector3 = finish_position
	var optimize_path: bool = true

	path = NavigationServer3D.map_get_path(
		map,
		start_position,
		target_position,
		optimize_path
	)
	
func pick_target():
	var condition = true
	while condition:
		var index = randi_range(0, GameLogic.cities.size()-1)
		finish_position = GameLogic.cities[index].global_position
		#position_title = GameLogic.cities[index].title
		if finish_position != start_position:
			navigation_agent.set_target_position(finish_position)
			condition = false

Look at the debug monitor from the documentation here Navigation debug tools — Godot Engine (latest) documentation in English

If you navigation map has a very detailed navigation mesh with thousands of polygons path search will be slow especially when the target can not be reached. So either use a less detailed navigation mesh or add a custom hierarchical pathfinding on top so you dont need to search such a complex mesh all the time for longer distances.

Not sure what “Trader jumps” means, that sounds more like a physics and movement code issue than anything because navigation alone can not do that. If you use the global position of you node make sure that this position is actually at the ground level of your collision. Make sure that your actor can reach the hovering navmesh surface with that position to get within desired distances. You can use the path height on the agent to lower it.

Thank you for your reply!
I use NavMesh for quite a large procedural terrain so probably my navmesh is really complex indeed. I’ll try to figure out how to make it less complex and hope it will work properly.
For this object the CollisionShape is disabled and during the movement along the rout everything is fine, so probably the issue is that navmesh in the scene is too complex to work with it fast enough.