Inconsistency in <class>.name in instantiated objects

Godot Version

4.2.2.stable

Question

I’m not sure if this is a bug, a problem in the way in which I’ve done things, or just a misunderstanding on my part.

I have a scene and script, CardBase.
In this script, I specify

class_name CardBase

In another scene, I dynamically instantiate X CardBase objects:

const CARDBASE= preload("res://Cards/CardBase.tscn")

func _ready():
    for i in range(2):
        var new_card = CARDBASE.instantiate()
        self.add_child(new_card)

Later on, when I want to get all instances that are of type CardBase, I can use

if child is CardBase:

And all instances that I expect to return true, will.

However, behaviour differs between instantiations when calling “child.name”, or “child.get_name()”

For the first instantiated object, the above returns “CardBase”, which is what I expect.

However, all instantiations after that return "@MarginContainerX@ where X < 2 < number of instantiations +1.

Is this expected behaviour, a problem with how I’m doing things, or a bug?

1 Like

It is the current behaviour. You can explicitly rename the objects but it’s ineficient to do so

2 Likes

This is the expected behavior.

Sibling nodes must have unique names. To speed up the instantiation of the nodes when adding them to the scene tree a generic name will be generated if it collides with another sibling node name unless you set force_readable_name to true when adding it with Node.add_child() . In this case the name will still be unique between its siblings being something like CardBase@2 for example.

1 Like

Thank you!

Is there any way to get the object’s class_name that I have specified without setting force_readable_name?

Effectively, what is the mechanism of the “is” operator in the line
if child is CardBase
and can I use a function call (without overrides) without explicitly needing to be aware of the type I’m checking for?

It’s not the class_name the name the node will try to use. It’s the name of the root node of the scene you are instantiating the one that it will be used. For example, if the root node of the scene is named Potato it does not matter which class_name the script attached to it will have. It will try to use Potato

I’m not sure I understand what you want to do. It’s not possible to get the class_name in Godot 4.2 but in Godot 4.3 you can use Script.get_global_name() to get it.

1 Like

When you refer to name here, are you referring to the name as it appears in the scene tree? The root name is CardBase, and that is the scene I am instantiating, yet it still returns “@MarginContainerX

I was just trying to see if there was an alternative to checking for a (named) node type.

e.g. something along the lines of

for child in children:
         print(child.name)  

In the above, I get the following output for e.g. 4 instantiations:

CardBase
@MarginContainer@2
@MarginContainer@3
@MarginContainer@4

It’s much easier to understand “CardBaseX” as opposed to, e.g. “MarginContainerX” here I think, which is what I originally expected.

As pointed before, you need to pass true to the parameter force_readable_name in the Node.add_child() function so it uses the name of the root node of the scene you are instantiating and adding.

The name of the node has nothing to do with the class_name you give a script.

The only way for now to know if a node is of an specific type or extends from one specific type is using the is keyword as you said in your first post.

1 Like