reckfellENGINE

Сигналы C#: параметры и время жизни

Объявите собственный сигнал, передайте значение и управляйте временем жизни подписки.

На этой странице

Собственный сигнал

Сохраните в Health.cs и прикрепите к обычной Entity:

C#
using Reckfell;

public partial class Health : Entity
{
    [Signal]
    public delegate void HealthChangedEventHandler(int remaining);

    public int Remaining { get; private set; } = 100;

    public void Damage(int amount)
    {
        if (amount <= 0 || Remaining == 0)
            return;

        Remaining = System.Math.Max(0, Remaining - amount);
        EmitSignal(SignalName.HealthChanged, Remaining);
    }
}

[Signal] ставится на открытый делегат. Его имя заканчивается на EventHandler; генератор создаёт событие HealthChanged и SignalName.HealthChanged. Параметры должны поддерживаться Variant. Соберите проект, чтобы сгенерированные члены появились в IDE и редакторе.

Damage(25) уменьшает здоровье со 100 до 75 и отправляет одно событие. Нулевой и отрицательный урон ничего не меняют. После смерти повторный урон не отправляет событие с тем же нулём. EmitSignal() запускает сигнал движка; вызывать событие как HealthChanged?.Invoke(...) здесь не нужно.

Слушатель с явным отключением

Сохраните HealthListener.cs, прикрепите к другой Entity и назначьте Source ссылкой на объект со скриптом Health. Назначение источника делается до запуска или до AddChild() из кода:

C#
using Reckfell;

public partial class HealthListener : Entity
{
    [Export] public Health? Source { get; set; }
    private Health? _subscribed;
    public int LastHealth { get; private set; }

    public override void _EnterTree()
    {
        if (!ReckfellObject.IsInstanceValid(Source))
            return;

        _subscribed = Source;
        _subscribed!.HealthChanged += OnHealthChanged;
        OnHealthChanged(_subscribed.Remaining);
    }

    public override void _ExitTree()
    {
        if (ReckfellObject.IsInstanceValid(_subscribed))
            _subscribed!.HealthChanged -= OnHealthChanged;
        _subscribed = null;
    }

    private void OnHealthChanged(int remaining)
    {
        LastHealth = remaining;
        ReckfellApi.Print("Health: ", remaining);
    }
}

Слушатель сразу считывает текущее значение: предыдущие события не воспроизводятся. При выходе из дерева подписка снимается. При повторном входе создаётся одна новая подписка, а не ещё одна поверх старой. Пример не переключает источник на лету: если изменять Source во время работы, реализуйте явное отключение старого и подключение нового.

Не рассчитывайте на автоматическое отключение всех C#-делегатов. Пользовательские сигналы и лямбды с захваченными переменными требуют внимания к времени жизни. Для отписки от лямбды сохраните тот же экземпляр делегата; новая лямбда с таким же текстом не снимает прежнюю подписку.

Ожидание одного сигнала

Следующий метод поместите внутрь скрипта Entity; нужны using Reckfell; и класс Health выше:

C#
public async System.Threading.Tasks.Task WaitForNextDamage(Health health)
{
    Variant[] values = await ToSignal(health, Health.SignalName.HealthChanged);
    ReckfellApi.Print(values[0].AsInt32());
}

Ожидание завершается следующим событием после начала ожидания. Сам ToSignal() не задаёт тайм-аут или отмену. Если отправитель удалён раньше события, нельзя считать продолжение гарантированным; для долгих игровых операций проектируйте отмену отдельно и проверяйте действительность объектов после await.

Если нужен OneShot или Deferred, используйте Connect() с Callable и ReckfellObject.ConnectFlags, проверьте возвращённый Error. Подписка через += не передаёт эти флаги. Справочник ReckfellObject, основы сигналов.

Документация Reckfell EngineНаверх ↑
БЫСТРЫЙ ПЕРЕХОДНачало работыEntity и иерархияC# & .NET 10Сцены и префабы
Руководства и полный API Reckfell K
reckfellENGINE
RECKFELL ACCOUNT

Вход в аккаунт

Войдите в аккаунт Reckfell.

Один аккаунт для всей платформы Reckfell.