Can you instantiate objects using reflection?

Godot Version

4.4-dev3

Question

Hello!
Is there any way to instantiate an object without knowing its class at compile time?

I’d like to make a variable that treats classes as values (like a pointer, or referencing them simply by their StringName), and then instantiate an Object of the same class of that variable’s value. I’ll give you a few examples.

In C#, there’s the Type class that functions like a “class” pointer, and then the Activator.CreateInstance function that takes a parameter of type Type and returns a new object.
Similarly in Unreal Engine, you can have pointers to UClasses (and their wrappers TSubclassOf), and the NewObject functions can take those pointers as parameters.

Does Godot have something similar to this? And if so, is that available to GDExtension and/or to GDScript, or is it strictly limited to core C++ engine?

I know you can do something similar by instantiating scenes and using PackedScene as their “class” pointer, but I’d prefer to instantiate a simple Object, which can’t reside in a scene.
I could probably create a custom Resource and treat it like a class ptr, using a virtual method that simply returns an instance of a specific type, and then make a subclass of that Resource for each subclass of my other type… But that’s a bit tedious.

Thanks in advance for any answer!

Yes you technically can by doing the following:

func create_instance(class_type: GDScript):
    return class_type.new()

func _ready():
    create_instance(Area2D)

But im not sure if it works with your own classes or only built-in ones

1 Like

I tried your solution but it doesn’t compile, because a variable of type GDScript can only accept actual scripts as values (.gd files), so Area2D is an invalid value. Nevertheless, it’s a cool thing I didn’t know, so thank you!

I’ve also found out about ClassDB::instantiate(), which pretty much does what I’ve been trying to do; it’s exposed both to GDExtension and to GDScript.
It works by passing the StringName of a class as argument.
From what I’ve found, there is no “class pointer”, so I’ll just have to use the name of the class itself.

1 Like