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`, який визначає сигнал `влучання`.
var player = Player.new()
# Ми знову використовуємо Signal.connect(), а також метод Callable.bind(),
# який повертає новий об'єкт Callable з параметром binds.
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, або визначений вручну.
[gdscript]
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!")
[/gdscript]
[csharp]
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!");
}
[/csharp][/codeblocks]
Хоча всі варіанти мають однаковий результат (сигнал [signal BaseButton.button_down] [code]кнопки [/code] буде підключено до [code]_on_button_down[/code]), [b]варіант 3[/b] пропонує найкращу перевірку: він виведе помилку під час компіляції, якщо або [code]button_down[/code] [Signal], або [code]_on_button_down[/code] [Callable] не визначені. З іншого боку, [b]варіант 2[/b] покладається лише на рядкові імена та зможе перевірити будь-яке з цих імен лише під час виконання: це призведе до помилки під час виконання, якщо [code]"button_down"[/code] не є сигналом, або якщо [code]"_on_button_down"[/code] не є методом в об'єкті [code]self[/code]. Основною причиною використання варіантів 1, 2 або 4 буде те, що ви насправді потрібно використовувати рядки (наприклад, для програмного підключення сигналів на основі рядків, зчитаних з файлу конфігурації). В іншому випадку, варіант 3 є рекомендованим (і найшвидшим) методом.
[b]Прив'язка та передача параметрів:[/b]
Синтаксис для зв'язування параметрів здійснюється через [method Callable.bind], який повертає копію [Callable] з його зв'язаними параметрами.
Під час виклику [method emit] або [method Object.emit_signal], Також можна передати параметри сигналу. Наведені нижче приклади показують зв'язок між цими параметрами сигналу та зв'язаними параметрами.
[codeblocks] [gdscript]
- func _ready():
# Це передбачає існування класу Player, який визначає сигнал влучання. 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("Hit by %s (level %d) with weapon %s for %d damage." % [hit_by, level, weapon_type, damage])[/gdscript]
- [csharp]
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($"Hit by {hitBy} (level {level}) with weapon {weaponType} for {damage} damage.");
}[/csharp]
[/codeblocks]
Примітка
Існують значні відмінності при використанні цього 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, якщо обидва сигнали діляться тим самим об'єктом і назвою.