В ходе моего текущего проекта я обнаружил, что переписываю похожие шаблоны во множестве разных классов для выдачи сигнала при каждом изменении переменной. В качестве примера целочисленной переменной этот код выглядит так:
Код: Выделить всё
[Signal] public delegate void ValueChangedEventHandler(int newValue);
private int _value;
public int Value
{
get => _value;
set
{
_value = value;
EmitSignal(SignalName.ValueChanged, Value);
}
}
К 20-й переменной, которую я создал с использованием этого формата, я начал уставать от беспорядка и повторений, поэтому решил, что могу создать вспомогательный класс, который обертывает эту функциональность. Я достиг этого с помощью:
Код: Выделить всё
using Godot;
public partial class NotifyOnChange : RefCounted
{
[Signal] public delegate void ChangedEventHandler(Variant newValue);
private T _value;
public T Value
{
get => _value;
set
{
_value = value;
EmitSignal(SignalName.Changed, Variant.From(Value));
}
}
public NotifyOnChange() { }
public NotifyOnChange(T value)
{
Value = value;
}
}
Это работает довольно хорошо и делает почти то, на что я надеялся, но у меня есть одна неприятная проблема, и я надеюсь, что есть обходной путь. Самой важной частью этой системы является сигнал, поскольку именно с ним будут взаимодействовать многие другие сценарии. Однако единственный способ объявить этот сигнал без ошибок — присвоить ему тип Variant. Это означает, что в каждом скрипте, подписывающемся на этот сигнал, сигнатура метода, ожидаемая для методов, подписанных на этот сигнал, будет выглядеть так:
Код: Выделить всё
private void OnValueChanged(Variant newValue)
{
// Logic here...
}
Моя проблема заключается в том, что каждый из этих методов будет иметь параметр типа Variant, что требует каждый раз приведения к нужному типу. Это добавляет накладные расходы, поскольку мне нужно будет запомнить, какого типа должно быть значение, и я обнаружил, что это добавляет больше хлопот, чем пользы, которую я получаю от использования этой системы.
Поэтому мой вопрос это:
Есть ли способ объявить сигнал, используя общий тип, например:
Код: Выделить всё
[Signal] public delegate void ChangedEventHandler(T newValue);
Попытка объявить сигнал таким образом в классе, который я показал выше, приводит к тому, что Godot не генерирует серверную часть сигнала и в целом, похоже, не работает. Я нахожу такое поведение странным, поскольку я пометил общий параметр T атрибутом [MustBeVariant] в объявлении класса, поэтому я ожидаю, что при использовании T не должно возникнуть никаких проблем. вместо Variant для типа параметра сигнала.
Что-то мне здесь не хватает, или это просто то, что пока невозможно в Godot?
Подробнее здесь:
https://stackoverflow.com/questions/784 ... -parameter