Skip to content

Node::_ready() and Node::_enter_tree() silently fail unless they are registered in register_methods #562

@valentinAlkan

Description

@valentinAlkan

This is something I knew about already but it got me again recently. It is not mentioned in the docs here, as far as I can tell, and I think that's very important information that should at least be in the example (the readme example does not show _ready or _enter_tree being used).

These are very important functions and I think there should be a note in the read me drawing users attention to this fact.

This is the existing example with my proposed changes in it already:

#include <Godot.hpp>
#include <Reference.hpp>

using namespace godot;

class SimpleClass : public Reference {
    GODOT_CLASS(SimpleClass, Reference);
public:
    SimpleClass() { }

    /** `_init` must exist as it is called by Godot. */
    void _init() { }

    void test_void_method() {
        Godot::print("This is test");
    }

    Variant method(Variant arg) {
        Variant ret;
        ret = arg;

        return ret;
    }

    static void _register_methods() {
        register_method("method", &SimpleClass::method);

        // All built in functions MUST be registered or they will be never called 
        // and there will be no warnings. Only the first parameter must match the 
        // function name that godot expects. If you wish to have them point to different
        // functions, you may do so they will be called at the normal times.
        register_method("_ready", &SimpleClass::_ready);
        register_method("_enter_tree", &SimpleClass::_enter_tree);
        register_method("_process", &SimpleClass::_process);

        /**
         * The line below is equivalent to the following GDScript export:
         *     export var _name = "SimpleClass"
         **/
        register_property<SimpleClass, String>("base/name", &SimpleClass::_name, String("SimpleClass"));

        /** Alternatively, with getter and setter methods: */
        register_property<SimpleClass, int>("base/value", &SimpleClass::set_value, &SimpleClass::get_value, 0);

        /** Registering a signal: **/
        // register_signal<SimpleClass>("signal_name");
        // register_signal<SimpleClass>("signal_name", "string_argument", GODOT_VARIANT_TYPE_STRING)
    }

    String _name;
    int _value;

    void set_value(int p_value) {
        _value = p_value;
    }

    int get_value() const {
        return _value;
    }

   void _ready() {
       // Here the function does not have to be named "_ready", so long as it is still 
       // registered as "_ready", it will still work.
       Godot:print("_ready");
   }

   void _enter_tree() {
       Godot:print("_enter_tree");
   }

   void _process(float delta) {
       Godot:print(delta);
   }
};

/** GDNative Initialize **/
extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) {
    godot::Godot::gdnative_init(o);
}

/** GDNative Terminate **/
extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o) {
    godot::Godot::gdnative_terminate(o);
}

/** NativeScript Initialize **/
extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) {
    godot::Godot::nativescript_init(handle);

    godot::register_class<SimpleClass>();
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions