I wrote a tutorial for a tower defense for RandomMomentania that chases a target, but I was getting the same issue when the target dies. From what I remember, I think I used a WeakRef to detect whether a node has been freed or not...
Edit: Here is the code snippet I used:
extends Area
# A WeakRef to the target.
# This is passed in from the tower.
var target_weak_ref = null;
func _physics_process(delta):
# Check if we have a weak reference to a target.
if (target_weak_ref != null):
# Get the object the reference points to.
var target = target_weak_ref.get_ref();
# If the reference is not pointing to null (in other words, if the target
# is still alive and/or in the scene)
if (target != null):
# If the target has a aim_position node, then rotate
# the arrow to look at that.
# If it does not, then rotate the arrow to look at the
# target's origin instead.
if (target.aim_position != null):
look_at(target.aim_position.global_transform.origin, Vector3(0, 1, 0))
else:
look_at(target.global_transform.origin, Vector3(0, 1, 0))
# If the reference is pointing to a null, then the target this arrow
# was created with must have died or have been removed from
# the scene in some other way.
# If the target is dead, then remove the reference to it.
else:
target_weak_ref = null;
And this is how I created the WeakRef that is passed to the projectile:
# If the tower's target is not going to be deleted...
if (target.is_queued_for_deletion() == false):
# Make a weak reference to the target and pass that to the arrow.
var target_weak_ref = weakref(target);
clone.target_weak_ref = target_weak_ref;
else:
# If the target is going to be deleted, then do not give the arrow a target.
clone.target_weak_ref = null;