Hello, its my first time. And im having problems.
My enemy follows me all good and dandy but sometimes it just doesnt and makes suicide.

As you can see the enemy paths are on point but at some point they break free from path and go in rando direction and does not follow target.

enemy.gd

extends CharacterBody3D
class_name Enemy

const SPEED = 5.0
const JUMP_VELOCITY = 4.5

@export var target: Node3D = null
@export var  player_node:CharacterBody3D

@onready var area_3d: Area3D = $Area3D
@onready var navigation_agent_3d: NavigationAgent3D = $NavigationAgent3D

var follow_target: bool = false
var timer: Timer



func _ready() -> void:
	area_3d.body_entered.connect(on_area_entered)
	add_child(timer)
	target = null
	pass

func _physics_process(delta: float) -> void:
	if player_node:
		if player_node.enemy_follow:
			follow_target = true
		else:
			follow_target = false
		
	if target and target is Player and follow_target: 
		navigation_agent_3d.target_position = target.global_position
		var direction = (navigation_agent_3d.get_next_path_position() - global_position).normalized()
		if direction:
			velocity.x = direction.x * SPEED
			velocity.z = direction.z * SPEED
			rotation.y=lerp_angle(rotation.y,atan2(-velocity.x,-velocity.z),0.2)

		else:
			velocity.x = move_toward(velocity.x, 0, SPEED)
			velocity.z = move_toward(velocity.z, 0, SPEED)

	# Add the gravity.
	if not is_on_floor():
		velocity += get_gravity() * delta
	move_and_slide()

func on_area_entered(body):
	print("enter: ",body)
	target = body
	pass

I have made a function that will flip the boolean player_node.enemy_follow when i press the "E" key

And i have attached the the player node to every enemy instance exported value.

World navigation

Enemy agent

  • kuligs2 replied to this.
  • I don't think that 3D avoidance has any effect if avoidance isn't enabled and safe velocity isn't being computed and used. But I guess that's probably not the issue here.

    Did they maybe collide and push each other somehow? I don't trust Godots physics sometimes.
    Does it happen if you set collision mask to not collide with enemy?

    EDIT: I have an idea.

    Do they all spawn within range of their area3d? Maybe they become the target on start. But in the first physics process their target becomes overwritten with the player as target. And once they are apart enough from each other and then meet again, they become the new target. And continue to move with their last velocity, because move_and_slide will be called with or without having a target and the velocity won't change as the current target is not a player.

    What does print say on body entered?

    I don't think that 3D avoidance has any effect if avoidance isn't enabled and safe velocity isn't being computed and used. But I guess that's probably not the issue here.

    Did they maybe collide and push each other somehow? I don't trust Godots physics sometimes.
    Does it happen if you set collision mask to not collide with enemy?

    EDIT: I have an idea.

    Do they all spawn within range of their area3d? Maybe they become the target on start. But in the first physics process their target becomes overwritten with the player as target. And once they are apart enough from each other and then meet again, they become the new target. And continue to move with their last velocity, because move_and_slide will be called with or without having a target and the velocity won't change as the current target is not a player.

    What does print say on body entered?

      trizZzle yesh indeed, the target was overwriting itself somehow because i forgot to check if body who enters the area3d is Player class, and then set the target to that body.

      Once i did that they all follow.

      kuligs2 func on_area_entered(body):
      print("enter: ",body)
      target = body
      pass

      func on_area_entered(body):
       	print("enter: ",body)
             if body is Player:
       	    target = body
      	pass

        kuligs2 btw. you don't need pass in your function. It is useful if you have a function that currently has no code inside to keep the editor from throwing errors or if you want to have a dummy function that you want to call from another script you are currently working on.

        func something():
        	pass

        No pass needed when there is code:

        func on_area_entered(body):
         	print("enter: ",body)
               if body is Player:
         	    target = body

          trizZzle thanks cap. Like you said, you need it when you have dummy func, and all funcs start out as dummy funcs so they end up with pass because aint nobody got time to clean it up 😃