Can I wire an Editor Timer's timeout callback to a C++ method?

Godot Version

` 4.3

Question

Hi everyone,

From the examples I’ve seen online, it looks like wiring a Timer in C++ requires creating a new Timer object in code. However, what I want to do is define the Timer in the editor and use its timeout callback to trigger a C++ method exposed to Godot, without involving GDScript in between.

Is this possible? Any advice would be greatly appreciated!

this is the code in the gdextention i want to bind the test_damage method

#include "health_manager.h"

void HealthManager::_bind_methods() 
{

    // Signals
    ADD_SIGNAL(MethodInfo("died"));
    ADD_SIGNAL(MethodInfo("healed"));
    ADD_SIGNAL(MethodInfo("damaged"));
    ADD_SIGNAL(MethodInfo("gibbed"));
    ADD_SIGNAL(MethodInfo("health_changed", PropertyInfo(Variant::INT, "cur_health"), PropertyInfo(Variant::INT, "max_health")));
    // Properties
    ClassDB::bind_method(D_METHOD("get_max_health"), &HealthManager::get_max_health);
    ClassDB::bind_method(D_METHOD("set_max_health", "value"), &HealthManager::set_max_health);
    ADD_PROPERTY(PropertyInfo(Variant::INT, "max_health"), "set_max_health", "get_max_health");

    ClassDB::bind_method(D_METHOD("get_gib_at"), &HealthManager::get_gib_at);
    ClassDB::bind_method(D_METHOD("set_gib_at", "value"), &HealthManager::set_gib_at);
    ADD_PROPERTY(PropertyInfo(Variant::INT, "gib_at"), "set_gib_at", "get_gib_at");

    ClassDB::bind_method(D_METHOD("get_verbose"), &HealthManager::get_verbose);
    ClassDB::bind_method(D_METHOD("set_verbose", "value"), &HealthManager::set_verbose);
    ADD_PROPERTY(PropertyInfo(Variant::BOOL, "verbose"), "set_verbose", "get_verbose");

    // Methods
    ClassDB::bind_method(D_METHOD("hurt", "damage_data"), &HealthManager::hurt);
    ClassDB::bind_method(D_METHOD("heal", "amount"), &HealthManager::heal);

    // Methods
    ClassDB::bind_method(D_METHOD("test_damage"), &HealthManager::test_damage);
   

   
}

void HealthManager::_ready() {
    cur_health = max_health;
    emit_signal("health_changed", cur_health, max_health);

    if (verbose) {
        UtilityFunctions::print("Starting health: ", cur_health, "/", max_health);
    }
}

void HealthManager::hurt(DamageData *damage_data) {
    
    if (cur_health <= 0) {
        return;
    }

    int damage_amount = damage_data->amount;
    cur_health -= damage_amount;

    if (cur_health <= gib_at) {
        emit_signal("gibbed");
    }

    if (cur_health <= 0) {
        emit_signal("died");
    }
    else {
        emit_signal("damaged");
    }

    emit_signal("health_changed", cur_health, max_health);

    if (verbose) {
        UtilityFunctions::print("Damaged for ", damage_amount, ", health: ", cur_health, "/", max_health);
    }
}

void HealthManager::heal(int amount) {
    if (cur_health <= 0) {
        return;
    }

    cur_health = Math::clamp(cur_health + amount, 0, max_health);
    emit_signal("healed");
    emit_signal("health_changed", cur_health, max_health);

    if (verbose) {
        UtilityFunctions::print("Healed for ", amount, ", health: ", cur_health, "/", max_health);
    }
}

void HealthManager::test_damage()
{
    DamageData* d = new DamageData();
    d->amount = 30;
    hurt(d);
}

but im getting this error in editor

In the screenshot it looks like the signal is attempting to connect to the Timer node instead of the HealthManager node. Can you verify that?

1 Like

I fixed that and now I am connected to the method, but the timer doesn’t trigger when running from the editor (Play button).

Interesting. Were there any compilation warnings/errors?

Are you able to call the test_damage() method with gdscript? (I know you want to avoid gdscript)

Can you post your HealthManager header file? Actually, if you can post an MRE or upload your project to test locally, that would be awesome.

i was able to run the timer after restarting the editor and starting it from the IDE (VSC++ )