Mocking Bird
Mocking Bird

Reputation: 176

Godot - Untarget dead enemy

So I want to set my _target_node to null when an enemy dies.

Here how I target an enemy: in my player.gd I have:

var _target_node: Node = null

func handle_target_lock():
    if Input.is_action_just_pressed("target_lock"):
        if _target_node:
            _target_node = null
        else:
            var enemies: Array = get_tree().get_nodes_in_group("Enemy")

            if enemies.size() > 0:
                _target_node = enemies[0]

    if _target_node:
        look_at(_target_node.global_transform.origin, Vector3.UP)

Problem is, when an enemy dies, _target_node is now referencing a deleted instance.

My enemy node emits a signal died when its hp is 0, but I don't know how to use this information to notify my player.

How do I notify the player that the targeted enemy is dead and _target_node should be set to null?

Godot version 3.5.1

Upvotes: 1

Views: 376

Answers (2)

Theraot
Theraot

Reputation: 40295

Problem is, when an enemy dies, _target_node is now referencing a deleted instance.

You can check for that:

if is_instance_valid(_target_node):

On the other hand, this form:

if _target_node:

Is checking if the variable is not zeroed. For an Object type (such as Node) it is checking if the variable is not set to null. However you can free Nodes while there are still references to them. As you might now, Node is not reference counted (it does not extend Reference), instead you free them manually with free or queue_free. When a Node is freed, Godot does not automatically turn the references that point to it into null, instead they become invalid references. We use is_instance_valid to check for that.

Upvotes: 1

Bugfish
Bugfish

Reputation: 1729

So you are saying there is a died signal so you could connect to it's die signal, when it is targeted:

if Input.is_action_just_pressed("target_lock"):
    if _target_node:
         #"died" should be renamed to your signal name!
        _target_node.disconnect("died",self, "on_target_died") # disconnect if you switch the target
        _target_node = null
    else:
        var enemies: Array = get_tree().get_nodes_in_group("Enemy")

        if enemies.size() > 0:
            _target_node = enemies[0]
            #"died" should be renamed to your signal name!
            _target_node.connect("died",self, "on_target_died")

func on_target_died():
    _target_node = null

Edit: It could help to pass the enemy as a parameter in the died signal so you can check, if the event was really fired from the enemy that is currently targeted. Otherwise there could be the chance, the player is still connected to the wrong enemy while switching targets

Upvotes: 2

Related Questions