Bram’s solution for fixing this minor error will work, but reacquiring the target multiple times every frame (because _process()
is called more frequently than _physics_process()
) is not optimal. Not a big deal, but it’s the principle of the thing (what if we had 10-million enemies, etc., etc.). Fortunately, there’s actually a nicer solution, which basically amounts to not having the Enemy’s NavigationAgent3D query a target on the first frame. Shown here:
(This issue was reopened for some reason, but the proposed solution from the first time around works just fine). Exact code I used in the Enemy script (and this would be useful for anything that requires you to skip a frame for initialization purposes):
func _ready() -> void:
#<omitted irrelevant code>
#disable enemy's _physics_process(), then defer a call of
#dump_first_physics_frame() until after this frame's processing
set_physics_process(false)
call_deferred("dump_first_physics_frame")
func dump_first_physics_frame() -> void:
#wait until just before the second physics_frame is ready to go, then
#re-enable _physics_process()
await get_tree().physics_frame
set_physics_process(true)
func _physics_process(delta: float) -> void:
#same code as Bram
navigation_agent_3d.target_position = player.global_position
var next_position = navigation_agent_3d.get_next_path_position()