Pathfinding Agent jitters when reaching destination

Godot Version

4.1.1 stable

Question

hey I followed a tutorial on pathfinding
I’m trying to make the NPC path to the marked destination (see attached images). it perfectly works until it reaches the position → there it just jitters and never comes to a halt

do you need more info? what might be the cause of the jitter? I’m guessing it’s because _process() is called every frame?

Tis is the agent’s code:

func _physics_process(delta: float) -> void:
	var direction := Vector3.ZERO
	
	nav_agent.target_position = target[self_id].global_position
	
	direction = nav_agent.get_next_path_position() - global_position
	direction = direction.normalized()
	
	velocity = velocity.lerp(direction * speed, accel * delta)
	
	look_at(get_node("../StrawberryStand").global_position)
	
	move_and_slide()

image
image

Thank you for your help!

You could try increasing the Target Desired Distance property in the inspector.

I’ve increased it very little, a lot and a middle value of it… Nothing worked :confused:

That would’ve been easiest, never mind. It will be because you’re setting the navigation target every _physics_process frame.

You could try wrapping it in an if statement that checks the distance first, something like:

if (global_position.distance_to(target[self_id].global_position)) < 1.0:
	
	nav_agent.target_position = target[self_id].global_position
	
	direction = nav_agent.get_next_path_position() - global_position
	direction = direction.normalized()
	
	velocity = velocity.lerp(direction * speed, accel * delta)
	
	look_at(get_node("../StrawberryStand").global_position)

You’ve changed your code from when I first saw it so you may need to fiddle with it a bit.

The docs recommend 2 checks, the second check should stop the jittering. They mention it somewhere in the docs.

func _physics_process(delta):
	# Do not query when the map has never synchronized and is empty.
	if NavigationServer3D.map_get_iteration_id(navigation_agent.get_navigation_map()) == 0:
		return
	if navigation_agent.is_navigation_finished():
		return
1 Like

Try only normalizing the direction if it’s greater than 1, so it doesn’t overshoot the target.

func _physics_process(delta: float) -> void:
	var direction := Vector3.ZERO
	
	nav_agent.target_position = target[self_id].global_position
	
	direction = nav_agent.get_next_path_position() - global_position
	if direction.length_squared() > 1.0:
		direction = direction.normalized()
	
	velocity = velocity.lerp(direction * speed, accel * delta)
	
	look_at(get_node("../StrawberryStand").global_position)
	
	move_and_slide()

I’d also recommend against using lerp, try using move_toward instead and set your accel to be in terms of pixels per second, a value twice or four times your speed might feel good. lerp is frame dependent, especially when multiplied by delta, where move_toward is not.

2 Likes

Thank you SO much! This is the solution and it looks fantastic.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.