-
-
Notifications
You must be signed in to change notification settings - Fork 21.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
get_class() returns wrong name, breaks signal connections, C++/GDExtension #69270
Comments
This seems to be a godotengine/godot-cpp issue. And please join a MRP, especially since there seem to be a lot of steps to take to compile the issue. |
Ok, maybe this should be moved to godot-cpp then. Also I attached an MRP. |
I think in Godot 3.x and probably also in Godot 4.0, get_class only returns the class name of the built-in class and no class named defined via "class_name" in GDScript. I personally don't mind, that's not the main issue, the main issue is with signals/receivers not working in C++ it seems. In Godot 4.0 with C++ for custom nodes, get_class returns the actual class name which is defined via GDCLASS macro and registered via ClassDB::register_class. But only IF the node has been created in the Editor and is loaded with the scene. If you instantiate the node at runtime with C++ code, then the class name is the one of the closest parent built-in class. That is different behavior for the same thing so a bug I guess. Main IssueThe problem with this is that emitting of signals as well as receiving of signals doesn't work with custom nodes created at runtime in C++ which is... a huge issue I think. The reason seems to be that the class name is used to search through the signals/receivers list so it will not find signals and receivers in custom nodes created at runtime due to the wrong class name. WorkaroundMy workaround is that I created hidden instances of my custom nodes in the Editor and then use duplicate() at runtime from C++ to create an actual instance....still not how it should be I think. So it would be cool if that could be fixed soon. |
I ran into this issue in 4.1.1-stable when it caused deferred calls (via
In addition to replicating the findings above, I found that any GDExtension-registered classes instantiated at runtime in C# via Instantiating GDExtension classes in GDScript at runtime also work as expected; something like
outputs So it seems that it is indeed only in C++ that the runtime-created GDExtension instances end up broken in the way this issue describes. |
As far as I can tell, this has the same root cause as godotengine/godot-cpp#1057 and specifically affects all objects instantiated in C++ from a user-defined GDExtension class when they are instantiated with an automatic storage duration (colloquially "on the stack") or any non- Although definitely an unexpected little trap for the unwary, it's unclear whether this is presently considered a bug. Were this to be fixed or changed, it would probably require changes in both this project and in godot-cpp, hence this note and issue link. |
This isn't a bug - with godot-cpp you have to use |
Godot version
4.0.beta6
System information
macOS Monterey, Apple M1
Issue description
If this is not a bug, I am sorry but there is not much documentation yet. If you create a class in C++ using GDExtension like this:
Next you register the class and stuff. If you then create a new node of this type (MyNode) using the Godot Editor, then everything runs fine and get_class() returns "MyNode". But if you instance that node via C++ like this:
It will print out "Node3D" and this seems to be a problem if you connect to signals via Object::connect because it seems that it uses get_class() or get_class_name() to get the list of methods and it won't find your method because it looks into the wrong class.
So this is either bug or I instantiated it the wrong way. I saw that Object and other builtin classes have a constructor taking the class name and if I pass the correct class name in there manually like this, it works:
(MyNode will pass down the class name.)
But I guess that is not how it is intended to be. Especially because it will crash if you pass down a class name but the node has been created via Editor. Which is why I couldn't automatically pass down "MyNode" via default constructor. I saw there is also get_class() but it is not virtual so I cannot override it.
Shouldn't that all be handled by the GDCLASS macro?
Steps to reproduce
Create a class in C++ using GDExtension like this:
If you instance that node via C++ like this:
It will print out "Node3D" instead of "MyNode".
Minimal reproduction project
To run this, you have to compile it so make sure to copy/clone the godot-cpp repo into the root folder. I couldn't include as file size it too big then. There is a SConstruct file which will build godot-cpp together with the extension then. So just move into the root folder and hit:
scons
To compile it. If you then open the godot project (inside project folder) and run the empty scene, on the output console you will see that the class name from the node added via Editor is "MyNode" and "Node" for the same one but created via C++.
gdextension_bug.zip
The text was updated successfully, but these errors were encountered: