Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
Signal
Вбудований тип, що представляє сигнал Object.
Опис
Signal — це вбудований тип Variant, який представляє сигнал екземпляра Object. Як і всі типи Variant, його можна зберігати у змінних та передавати у функції. Сигнали дозволяють усім підключеним Callable (а отже, і відповідним об’єктам) відстежувати події та реагувати на них без прямого посилання один на одного. Це забезпечує гнучкість коду та спрощує його управління. Ви можете перевірити, чи має Object задане ім'я сигналу, використовуючи Object.has_signal().
У GDScript сигнали можна оголошувати за допомогою ключового слова signal. У C# ви можете використовувати атрибут [Signal] на делегаті.
signal attacked
# Можна оголосити додаткові аргументи.
# Ці аргументи повинні бути передані під час випромінювання сигналу.
signal item_dropped(item_name, amount)
[Signal]
delegate void AttackedEventHandler();
// Можна оголосити додаткові аргументи.
// Ці аргументи повинні бути передані під час випромінювання сигналу.
[Signal]
delegate void ItemDroppedEventHandler(string itemName, int amount);
Підключення сигналів є однією з найпоширеніших операцій у Godot, і API надає багато варіантів для цього, які описані нижче. Блок коду нижче демонструє рекомендований підхід.
func _ready():
var button = Button.new()
# `button_down` тут є типом Signal Variant. Тому ми викликаємо метод Signal.connect(), а не Object.connect().
# Дивіться обговорення нижче для більш детального огляду API.
button.button_down.connect(_on_button_down)
# Це передбачає, що існує клас `Player`, який визначає сигнал `hit`.
var player = Player.new()
# Ми знову використовуємо Signal.connect(), а також метод Callable.bind(),
# який повертає новий Callable з прив'язаними параметрами.
player.hit.connect(_on_player_hit.bind("sword", 100))
func _on_button_down():
print("Button down!")
func _on_player_hit(weapon_type, damage):
print("Hit with weapon %s for %d damage." % [weapon_type, damage])
public override void _Ready()
{
var button = new Button();
// C# підтримує передачу сигналів як подій, тому ми можемо використовувати цю ідіоматичну конструкцію:
button.ButtonDown += OnButtonDown;
// Це передбачає, що існує клас `Player`, який визначає сигнал `Hit`.
var player = new Player();
// Ми можемо використовувати лямбди, коли нам потрібно прив'язати додаткові параметри.
player.Hit += () => OnPlayerHit("sword", 100);
}
private void OnButtonDown()
{
GD.Print("Button down!");
}
private void OnPlayerHit(string weaponType, int damage)
{
GD.Print($"Hit with weapon {weaponType} for {damage} damage.");
}
Object.connect() або Signal.connect()?
Як бачимо вище, рекомендованим методом підключення сигналів не є Object.connect(). У наведеному нижче блоці коду показано чотири варіанти підключення сигналів: із використанням цього застарілого методу або рекомендованого connect(), а також із використанням неявного Callable або визначеного вручну.
func _ready():
var button = Button.new()
# Варіант 1: Object.connect() з неявним Callable для визначеної функції.
button.connect("button_down", _on_button_down)
# Варіант 2: Object.connect() з побудованим Callable з використанням об’єкта-цілі та імені методу.
button.connect("button_down", Callable(self, "_on_button_down"))
# Варіант 3: Signal.connect() з неявним Callable для визначеної функції.
button.button_down.connect (_on_button_down)
# Варіант 4: Signal.connect() із сконструйованим Callable з використанням об’єкта-цілі та імені методу.
button.button_down.connect(Callable(self, "_on_button_down"))
func _on_button_down():
print("Button down!")
public override void _Ready()
{
var button = new Button();
// Варіант 1: У C# ми можемо використовувати сигнали як події та підключатися за допомогою цього ідіоматичного синтаксису:
button.ButtonDown += OnButtonDown;
// Варіант 2: GodotObject.Connect() із сконструйованим Callable з групи методів.
button.Connect(Button.SignalName.ButtonDown, Callable.From(OnButtonDown));
// Варіант 3: GodotObject.Connect() із сконструйованим Callable, використовуючи об’єкт-ціль та ім’я методу.
button.Connect(Button.SignalName.ButtonDown, new Callable(this, MethodName.OnButtonDown));
}
private void OnButtonDown()
{
GD.Print("Button down!");
}
Хоча всі варіанти дають однаковий результат (сигнал button BaseButton.button_down буде підключено до _on_button_down), варіант 3 забезпечує найкращу перевірку: він видасть помилку під час компіляції, якщо або button_down Signal або _on_button_down Callable не визначені. З іншого боку, варіант 2 покладається лише на імена рядків і зможе перевірити їх лише під час виконання: він видасть помилку під час виконання, якщо "button_down" не є сигналом або якщо "_on_button_down" не є методом в об’єкті self. Основною причиною використання варіантів 1, 2 або 4 є необхідність фактичного використання рядків (наприклад, для програмного підключення сигналів на основі рядків, прочитаних із файлу конфігурації). В іншому випадку рекомендується (і найшвидший) варіант 3.
Прив'язування та передача параметрів:
Синтаксис прив'язки параметрів здійснюється за допомогою Callable.bind(), який повертає копію Callable з прив'язаними параметрами.
При виклику emit() або Object.emit_signal() також можна передавати параметри сигналу. Наведені нижче приклади показують взаємозв'язок між цими параметрами сигналу та прив'язаними параметрами.
func _ready():
# Тут передбачається, що існує клас `Player`, який визначає сигнал `hit`.
var player = Player.new()
# Використання Callable.bind().
player.hit.connect(_on_player_hit.bind("sword", 100))
# Параметри, додані під час випромінювання сигналу, передаються першими.
player.hit.emit("Dark lord", 5)
# Ми передаємо два аргументи під час випромінювання (`hit_by`, `level`),
# і прив'язуємо ще два аргументи під час підключення (`weapon_type`, `damage`).
func _on_player_hit(hit_by, level, weapon_type, damage):
print("Вдарив %s (рівень %d) зброєю %s, завдавши %d шкоди." % [hit_by, level, weapon_type, damage])
public override void _Ready()
{
// Це передбачає, що існує клас `Player`, який визначає сигнал `Hit`.
var player = new Player();
// Використання лямбда-виразів, що створюють замикання, яке фіксує додаткові параметри.
// Лямбда отримує лише параметри, визначені делегатом сигналу.
player.Hit += (hitBy, level) => OnPlayerHit(hitBy, level, "sword", 100);
// Параметри, додані під час випромінювання сигналу, передаються першими.
player.EmitSignal(SignalName.Hit, "Dark lord", 5);
}
// Ми передаємо два аргументи під час випромінювання (`hit_by`, `level`),
// і прив'язуємо ще два аргументи під час підключення (`weapon_type`, `damage`).
private void OnPlayerHit(string hitBy, int level, string weaponType, int damage)
{
GD.Print($"Вдарено {hitBy} (рівень {level}) зброєю {weaponType} з ушкодженням {damage}.");
}
Примітка: У булевому контексті сигнал буде обчислюватися як false, якщо він нульовий (див. is_null()). В іншому випадку сигнал завжди обчислюватиметься як true.
Примітка
Існують значні відмінності при використанні цього API із С#. Більше інформації: ref:doc_c_sharp_differences.
Посібники
Конструктори
Signal() |
|
Signal(object: Object, signal: StringName) |
Методи
void |
disconnect(callable: Callable) |
void |
emit(...) vararg const |
get_connections() const |
|
get_name() const |
|
get_object() const |
|
get_object_id() const |
|
has_connections() const |
|
is_connected(callable: Callable) const |
|
is_null() const |
Оператори
operator !=(right: Signal) |
|
operator ==(right: Signal) |
Описи конструкторів
Створює порожній Signal без прив'язаного до об'єкта чи імені сигналу.
Constructs a Signal як копія даної Signal.
Signal Signal(object: Object, signal: StringName)
Створює об’єкт Signal, який посилається на сигнал із назвою signal у вказаному object.
Описи методів
int connect(callable: Callable, flags: int = 0) 🔗
З'єднує цей сигнал із зазначеним callable. Також можна додати додаткові flags для налаштування поведінки з'єднання (див. константи ConnectFlags). Ви можете надати додаткові аргументи підключеному callable за допомогою Callable.bind().
Сигнал може бути підключений до того самого Callable лише один раз. Якщо сигнал вже підключено, цей метод повертає @GlobalScope.ERR_INVALID_PARAMETER та генерує помилку, якщо сигнал не підключено з Object.CONNECT_REFERENCE_COUNTED. Щоб запобігти цьому, спочатку використовуйте is_connected() для перевірки наявності існуючих з'єднань.
for button in $Buttons.get_children():
button.pressed.connect(_on_pressed.bind(button))
func _on_pressed(button):
print(button.name, "було натиснуто")
Примітка: Якщо об'єкт callable звільниться, з'єднання буде втрачено.
void disconnect(callable: Callable) 🔗
Відключення цього сигналу з вказаного Callable. Якщо підключення не існує, генерує помилку. Використовуйте method_connected, щоб переконатися, що підключення існує.
void emit(...) vararg const 🔗
Зніміть цей сигнал. Всі Callable, підключені до цього сигналу, будуть запущені. Цей метод підтримує змінну кількість аргументів, тому параметри можуть бути передані як окремий список коми.
Array get_connections() const 🔗
Повернутися до Array підключень до цього сигналу. Кожен з'єднання представлений як Dictionary, який містить три записи:
signal- посилання на цей сигнал;Callable- посилання на підключений Callable;flags- це поєднання об'єкту [enum. Роз'єм.
StringName get_name() const 🔗
Повертає назву цього сигналу.
Повернення об'єкта, що видає цей сигнал.
Повертає ідентифікатор об'єкта, який випромінює цей сигнал (див. Object.get_instance_id()).
bool has_connections() const 🔗
Повертає true, якщо будь-який Callable підключено до цього сигналу.
bool is_connected(callable: Callable) const 🔗
Повертає true, якщо зазначений Callable підключений до цього сигналу.
Повертає true, якщо цей Signal не має об’єкта, а назва сигналу порожня. Еквівалент singal == Singal().
Описи операторів
bool operator !=(right: Signal) 🔗
Повертає true, якщо сигнали не діляться тим самим об'єктом і назвою.
bool operator ==(right: Signal) 🔗
Повертає true, якщо обидва сигнали діляться тим самим об'єктом і назвою.