godotengine / godot-cpp

C++ bindings for the Godot script API
MIT License
1.69k stars 528 forks source link

_process behavior of GDExtension classes in editor and when added as child #1467

Closed TvdSmagt closed 4 months ago

TvdSmagt commented 4 months ago

Godot version

4.2.2-stable_linux

godot-cpp version

4.2

System information

Linux Ubuntu 22.04

Issue description

I am getting started with GDExtension while having work experience with C++ and previous hobby experience with Godot/GDScript. I have run into some specific behavior related to _process which surprised me and I could not find documented anywhere or referenced before.

I created a GDExtension class Parent which when added through the editor will immediately start calling _process, without specifically specifying it as a tool. But, when I have it add my Child class in its constructor (or elsewhere) with add_child, it will not call any of its default functions (_bind_methods, _process) either in the editor or while running the project.

I would expect the Parent plugin to only start running _process in the editor when specifically being set as a tool.

I would expect that the child node _process would be called when running the project, possibly requiring a ClassDB::bind_method(D_METHOD("_process", "delta"), &Child::_process);

Steps to reproduce

Add Parent and Child class attached to register_types and build.

ClassDB::register_class<Parent>();
ClassDB::register_class<Child>();

Add Parent node in new scene, it should print:

Create Node
Parent::Parent
ChildConstruct::Child
ChildProcess::Child

With ChildProcess being constructed in the Parent::_process call

When running the scene it will report:

Parent::_bind_methods
Child::_bind_methods
Parent::Parent
ChildConstruct::Child
ChildProcess::Child

Minimal reproduction project

parent_child.zip

AThousandShips commented 4 months ago

Thank you for reporting, this is intended, extensions, like modules, always run

In 4.3 you can use runtime classes

For more details see:

TvdSmagt commented 4 months ago

Hi @AThousandShips, thank you for the swift reply.

What about the child classes _process not being called?

AThousandShips commented 4 months ago

You need to add _bind_methods to all classes, see:

But it's unclear from your description, but in either case you should make one report for one bug, so if that's not the issue please open a new report that's specific to that bug

Also never bind _process and similar methods, it's not correct

Also you can't use complex constructors with extensions at the moment, see:

Also you can't construct objects like that, that probably is the main cause, you don't call the constructor that way, you use memnew

Also Godot objects are not compatible with smart pointers, and you shouldn't use them like this, especially since Node is handled by the parent, so you can't delete it this way that'll cause memory issues

TvdSmagt commented 4 months ago

https://github.com/godotengine/godot-cpp/issues/1468

I created a new issue. I hope this one illustrates the problem I am facing with child nodes _process.

TvdSmagt commented 4 months ago

Ah I missed your edited comment. I closed the other ticket as instead the issue was that I was using smart pointers instead of memnew.

I do think it would be good to add this to the documentation. Could I contribute to that?

AThousandShips commented 4 months ago

I do think it would be good to add this to the documentation.

What part? The memnew stuff is documented here, and I don't think anything else here should be surprising, you shouldn't assume you can use smart pointers, nor could we provide details on everything else you shouldn't use IMO

It's hard to work out exactly what to document as most is basic c++, but most is already documented, in places like here, and here, but might be useful to make it a bit easier to access

TvdSmagt commented 4 months ago

Thank you for the links, I agree with you that those pages cover the information I was missing.

I think the reason is that I have not found them before is because they are located under the "Contributing" section of the documentation, whereas I was going off the GDExtension C++ Example inside the "Manuals". For someone like me, who just wants to follow a manual and then play around, spitting through the Contributing pages did not come to mind when searching for a solution.

Personally, to avoid others falling into the same errors as me, I would point the user at the end of the tutorial to those pages for further information. Maybe even extend the example to also show how to acually add and free a child node.

Besides that, the example text now specifically states:

The second is our _process function, which will work exactly the same as the _process function you're used to in GDScript.

Which IMO is not really true, as it will always run, contradictory to the GDScript _process which will by default only run in the project.

AThousandShips commented 4 months ago

Which IMO is not really true, as it will always run, contradictory to the GDScript _process which will by default only run in the project.

Except the line is in a part of code that's an editor plugin running in the editor, which is made very clear here, the only detail is that it doesn't explicitly say it runs in the editor, but it shows that it's done

Personally, to avoid others falling into the same errors as me, I would point the user at the end of the tutorial to those pages for further information. Maybe even extend the example to also show how to acually add and free a child node.

That's a good point, feel free to add that here, make sure to follow the instructions and target the right branch