Search code examples
godotgdscript

GODOT add_to_group with an inheritance variable


I have several nodes under several different parent nodes. Each child node inherets from a base script as they all have the same functions, just different individual variable values. On "_ready", I want each node to add itself to a group named after its parent.

Base.gd:

extends Area2D

export var _parent: String

func _ready() -> void:
     add_to_group(_parent)

Node1.gd

extends "res://Base.gd"

func _ready() -> void:
     _parent = "MyParentNode"

This seems like it should add Node1 to the group "MyParentNode". I also get this debug error:

add_to_group: Condition "!p_identifier.operator String().length()" is true.


Solution

  • Godot will call _ready on the base class first, recursively. I go into detail on how Godot calls _ready in my answer to How to know if an overriden method calls its super method or not?

    Thus, Godot will call this:

    func _ready() -> void:
         add_to_group(_parent)
    

    And then this:

    func _ready() -> void:
         _parent = "MyParentNode"
    

    As a result, _parent was not set when calling add_to_group.


    Now, given that you want to set a variable, I suggest using setget:

    extends Area2D
    
    export var _parent:String setget ser_parent
    
    func set_parent(new_value:String) -> void:
        if _parent == new_value:
            return
    
        if is_in_group(_parent):
            remove_from_group(_parent)
    
        add_to_group(new_value)
        _parent = new_value
    

    That way, every time the derived class sets _parent, it will be adding and removing the node from groups accordingly.


    By the way, and just in case, if you only plan to use this for is_in_group, then you don't need groups at all. Instead of checking if node.is_in_group(something) you can just check if node._parent == something.

    Furthermore, if this is predicated on the parent node, you can check the parent node with get_parent(): if node.get_parent() == something or if node.get_parent().name == something. And I remind you about get_children.