Signal

Встроенный тип, представляющий сигнал Object.

Описание

Signal — это встроенный тип Variant, который представляет сигнал экземпляра Object. Как и все типы Variant, он может храниться в переменных и передаваться в функции. Сигналы позволяют всем подключенным Callable (и соответственно, их соответствующим объектам) прослушивать и реагировать на события, не ссылаясь напрямую друг на друга. Это сохраняет код гибким и простым в управлении. Вы можете проверить, имеет ли Object заданное имя сигнала, используя Object.has_signal().

В GDScript сигналы можно объявлять с помощью ключевого слова signal. В C# вы можете использовать атрибут [Signal] для делегата.

signal attacked

# Могут быть объявлены дополнительные аргументы.
# Эти аргументы должны быть переданы при отправке сигнала.
signal item_dropped(item_name, 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 с параметром binds.
    player.hit.connect(_on_player_hit.bind("sword", 100))

func _on_button_down():
    print("Кнопка нажата!")

func _on_player_hit(weapon_type, damage):
    print("Hit with weapon %s for %d damage." % [weapon_type, damage])

``Object.connect()`` или ``Signal.connect()``?

Как видно выше, рекомендуемый метод для подключения сигналов — не Object.connect(). В блоке кода ниже показаны четыре варианта подключения сигналов с использованием либо этого устаревшего метода, либо рекомендуемого connect(), а также с использованием либо неявного Callable, либо определенного вручную.

func _ready():
    var button = Button.new()
    # Вариант 1: Object.connect() с неявным вызовом для определенной функции.
    button.connect("button_down", _on_button_down)
    # Вариант 2: Object.connect() с созданным Callable, использующим целевое имя объекта и метода.
    button.connect("button_down", Callable(self, "_on_button_down"))
    # Вариант 3: Signal.connect() с неявным вызовом для определенной функции.
    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("Кнопка нажата!")

Хотя все варианты имеют одинаковый результат (BaseButton.button_down button будет подключен к _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("Hit by %s (level %d) with weapon %s for %d damage." % [hit_by, level, weapon_type, damage])

Примечание

Существуют заметные различия при использовании данного API с C#. Подробнее см. API различия C# и GDScript.

Обучающие материалы

Конструкторы

Signal

Signal()

Signal

Signal(from: Signal)

Signal

Signal(object: Object, signal: StringName)

Методы

int

connect(callable: Callable, flags: int = 0)

void

disconnect(callable: Callable)

void

emit(...) vararg const

Array

get_connections() const

StringName

get_name() const

Object

get_object() const

int

get_object_id() const

bool

has_connections() const

bool

is_connected(callable: Callable) const

bool

is_null() const

Операторы

bool

operator !=(right: Signal)

bool

operator ==(right: Signal)


Описания конструктора

Signal Signal() 🔗

Создает пустой Signal без привязанного имени объекта или сигнала.


Signal Signal(from: Signal)

Создает 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, " was pressed")

Примечание: Если объект callable освобождён, соединение будет потеряно.


void disconnect(callable: Callable) 🔗

Отключает этот сигнал от указанного Callable. Если соединение не существует, генерирует ошибку. Используйте is_connected(), чтобы убедиться, что соединение существует.


void emit(...) vararg const 🔗

Выдает этот сигнал. Все Callable, подключенные к этому сигналу, будут активированы. Этот метод поддерживает переменное количество аргументов, поэтому параметры можно передавать в виде списка, разделенного запятыми.


Array get_connections() const 🔗

Возвращает Array соединений для этого сигнала. Каждое соединение представлено как Dictionary, который содержит три записи:

  • signal — ссылка на этот сигнал;

  • callable — ссылка на подключенный Callable;

  • flags — комбинация ConnectFlags.


StringName get_name() const 🔗

Возвращает имя этого сигнала.


Object get_object() const 🔗

Возвращает объект, испускающий этот сигнал.


int get_object_id() const 🔗

Возвращает идентификатор объекта, испускающего этот сигнал (см. Object.get_instance_id()).


bool has_connections() const 🔗

Возвращает true, если к этому сигналу подключен какой-либо Callable.


bool is_connected(callable: Callable) const 🔗

Возвращает true, если указанный Callable подключен к этому сигналу.


bool is_null() const 🔗

Возвращает true, если этот Signal не имеет объекта и имя сигнала пустое. Эквивалентно signal == Signal().


Описания оператора

bool operator !=(right: Signal) 🔗

Возвращает true, если сигналы не имеют одного и того же объекта и имени.


bool operator ==(right: Signal) 🔗

Возвращает true, если оба сигнала имеют один и тот же объект и имя.