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.

Примірник із сигналами

Сигнали забезпечують спосіб відокремлення ігрових об’єктів, що дозволяє уникнути примусового фіксованого розташування вузлів. Однією з ознак того, що може знадобитися сигнал, є те, що ви використовуєте get_parent(). Звернення безпосередньо до батьківського вузла означає, що ви не можете легко перемістити цей вузол в інше місце в дереві сцени. Це може бути особливо проблематично, коли ви створюєте екземпляри об’єктів під час виконання та можете розмістити їх у довільному місці в дереві запущеної сцени.

Нижче ми розглянемо приклад такої ситуації: стрільба кулями.

Приклад зйомки

Розглянемо персонаж гравця, який може обертатися та стріляти в бік миші. Щоразу, коли натискається кнопка миші, ми створюємо екземпляр кулі в місці розташування гравця. Дивіться Створення екземплярів для деталей.

Ми будемо використовувати Area2D для кулі, яка рухається прямолінійно із заданою швидкістю:

extends Area2D

var velocity = Vector2.RIGHT

func _physics_process(delta):
    position += velocity * delta

Однак, якщо кулі додаються як діти гравця, вони залишаться «прикріпленими» до гравця, коли він обертається:

../../_images/signals_shoot1.gif

Натомість нам потрібно, щоб кулі не залежали від руху гравця — після пострілу вони мають рухатися по прямій лінії, і гравець більше не зможе на них впливати. Замість того, щоб додавати кулю до дерева сцен як дочірню для гравця, доцільніше додати кулю як дочірню для «основної» ігрової сцени, яка може бути батьківською для гравця або навіть вище в дереві.

Ви можете зробити це, додавши кулю безпосередньо до головної сцени:

var bullet_instance = Bullet.instantiate()
get_parent().add_child(bullet_instance)

Однак це призведе до іншої проблеми. Тепер, якщо ви спробуєте самостійно протестувати свою сцену «Програвач», вона вийде з ладу під час зйомки, оскільки немає батьківського вузла для доступу. Це значно ускладнює незалежне тестування коду вашого гравця, а також означає, що якщо ви вирішите змінити структуру вузла вашої основної сцени, батьківський вузол гравця може більше не бути відповідним вузлом для отримання куль.

Вирішення цього полягає у використанні сигналу для «випромінювання» куль від гравця. Тоді гравцеві не потрібно «знати», що станеться з кулями після цього — будь-який вузол, підключений до сигналу, може «отримати» кулі та вжити відповідних дій, щоб їх породити.

Ось код для гравця, який використовує сигнали для випуску кулі:

extends Sprite2D

signal shoot(bullet, direction, location)

var Bullet = preload("res://bullet.tscn")

func _input(event):
    if event is InputEventMouseButton:
        if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
            shoot.emit(Bullet, rotation, position)

func _process(delta):
    look_at(get_global_mouse_position())

У головній сцені ми підключаємо сигнал гравця (він з’явиться у вкладці «Вузол» Інспектора)

func _on_player_shoot(Bullet, direction, location):
    var spawned_bullet = Bullet.instantiate()
    add_child(spawned_bullet)
    spawned_bullet.rotation = direction
    spawned_bullet.position = location
    spawned_bullet.velocity = spawned_bullet.velocity.rotated(direction)

Тепер кулі рухатимуться незалежно від обертання гравця:

../../_images/signals_shoot2.gif