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.

Використання inputEvent

Що це таке?

Управління входом, як правило, складне, незалежно від ОС, або платформи. Щоб трохи полегшити це, передбачений спеціальний вбудований тип Вхідних Подій InputEvent. Цей тип даних можна настроїти так, щоб він містив кілька типів вхідних подій. Вхідні події проходять через рушій і можуть бути отримані в декількох місцях, в залежності від мети.

Ось короткий приклад, закривання гри при натисканні клавіші Esc:

func _unhandled_input(event):
    if event is InputEventKey:
        if event.pressed and event.keycode == KEY_ESCAPE:
            get_tree().quit()

Однак чистіше і зручніше використовувати надану функцію Карти Введення InputMap, яка дозволяє визначати дії введення і призначати їм різні клавіші. Таким чином, ви можете визначити кілька клавіш для однієї дії (наприклад, клавішу виходу з клавіатури та кнопку пуску на геймпаді). Потім ви зможете легше змінити ці призначення в параметрах проекту, не оновлюючи код, і навіть створити функцію перепризначення клавіш, щоб дозволити гравцям призначати зручні для них клавіші!

Карту вводу можна настроїти в розділі Проект > Параметри проекту > Input Map, а потім використати ці дії, наприклад, так:

func _process(delta):
    if Input.is_action_pressed("ui_right"):
        # Move right.

Як усе це працює?

Кожна подія введення походить від користувача/гравця (хоча можна згенерувати InputEvent і передати їх назад механізму, що корисно для жестів). DisplayServer для кожної платформи читатиме події з операційної системи, а потім передасть їх до кореня Window.

Viewport вікна робить досить багато речей з отриманим введенням, у порядку:

../../_images/input_event_flow.webp
  1. Якщо вікно перегляду вбудовує Windows, вікно перегляду намагається інтерпретувати подію в якості диспетчера вікон (наприклад, для зміни розміру або переміщення вікон).

  2. Далі, якщо вбудоване вікно перебуває у фокусі, подія надсилається до цього вікна та обробляється у вікні перегляду, а потім вважається обробленою. Якщо жодне вбудоване вікно не перебуває у фокусі, подія надсилається до вузлів поточного вікна перегляду у такому порядку.

  3. По-перше, стандартна функція Node._input() буде викликана в будь-якому вузлі, який замінює її (і не вимкнув обробку вхідних даних за допомогою Node.set_process_input()). Якщо будь-яка функція споживає подію, вона може викликати Viewport.set_input_as_handled(), і подія більше не поширюватиметься. Це гарантує, що ви можете фільтрувати всі події, які вас цікавлять, навіть до графічного інтерфейсу користувача. Для ігрового процесу Node._unhandled_input() зазвичай краще підходить, оскільки дозволяє графічному інтерфейсу користувача перехоплювати події.

  4. По-друге, він намагатиметься надіслати вхідні дані до графічного інтерфейсу користувача та перевірити, чи може якийсь елемент керування отримати їх. Якщо так, Control буде викликано через віртуальну функцію Control._gui_input() і буде видано сигнал «gui_input» (цю функцію можна повторно реалізувати за допомогою скрипт шляхом успадкування від нього). Якщо елемент керування хоче «спожити» подію, він викличе Control.accept_event(), і подія більше не поширюватиметься. Використовуйте властивість Control.mouse_filter, щоб контролювати, чи сповіщати Control про події миші через Control._gui_input() зворотний виклик і чи ці події поширюються далі.

  5. Якщо досі ніхто не використовував подію, зворотній виклик Node._shortcut_input() буде викликано, якщо перевизначено (і не вимкнено за допомогою Node.set_process_shortcut_input()). Це відбувається лише для InputEventKey, InputEventShortcut і InputEventJoypadButton. Якщо будь-яка функція споживає подію, вона може викликати Viewport.set_input_as_handled(), і подія більше не поширюватиметься. Зворотний виклик швидкого введення ідеально підходить для обробки подій, призначених як ярлики.

  6. Якщо досі ніхто не використовував подію, зворотній виклик Node._unhandled_key_input() буде викликано, якщо перевизначено (і не вимкнено за допомогою Node.set_process_unhandled_key_input()). Це відбувається, лише якщо подією є InputEventKey. Якщо будь-яка функція споживає подію, вона може викликати Viewport.set_input_as_handled(), і подія більше не поширюватиметься. Зворотний виклик необробленого введення клавіш ідеально підходить для ключових подій.

  7. Якщо досі ніхто не використовував подію, зворотній виклик Node._unhandled_input() буде викликано, якщо перевизначено (і не вимкнено за допомогою Node.set_process_unhandled_input()). Якщо будь-яка функція споживає подію, вона може викликати Viewport.set_input_as_handled(), і подія більше не поширюватиметься. Необроблений зворотний виклик ідеально підходить для повноекранних ігрових подій, тому вони не приймаються, коли графічний інтерфейс активний.

  8. Якщо поки що ніхто не хотів події, а Object Picking увімкнено, подія використовується для вибору об’єкта. Для кореневого вікна перегляду це також можна ввімкнути в Project Settings. У випадку 3D-сцени, якщо Camera3D призначено вікну перегляду, буде спрямовано промінь у світ фізики (у напрямку променя від клацання). Якщо цей промінь потрапляє на об’єкт, він викличе функцію CollisionObject3D._input_event() у відповідному фізичному об’єкті. У випадку 2D-сцени концептуально те саме відбувається з CollisionObject2D._input_event().

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

../../_images/input_event_scene_flow.webp

Примітка

Цей порядок не застосовується до Control._gui_input(), який використовує інший метод на основі розташування події або фокусованого елемента керування. Події миші графічного інтерфейсу також переміщуються вгору по дереву сцен, підпорядковуючись обмеженням Control.mouse_filter, описаним вище. Однак, оскільки ці події спрямовані на певні елементи керування, подію отримують лише прямі предки цільового вузла керування. Події клавіатури та джойстика графічного інтерфейсу не переміщуються вгору по дереву сцен і можуть бути оброблені лише контролем, який їх отримав. В іншому випадку вони будуть розповсюджуватися як події не графічного інтерфейсу через Node._unhandled_input().

Оскільки Viewports не надсилають події до інших SubViewports, потрібно використати один із наведених нижче методів:

  1. Використовуйте SubViewportContainer, який автоматично надсилає події своєму дочірньому SubViewports після Node._input() або Control._gui_input ().

  2. Реалізація розповсюдження подій на основі індивідуальних вимог.

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

Анатомія InputEvent

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

Існує кілька спеціалізованих типів InputEvent, описаних в таблиці нижче:

Подія

Опис

InputEvent

Порожня вхідна подія.

InputEventKey

Містить код ключа та значення Unicode, а також модифікатори.

InputEventMouseButton

Містить інформацію про кліки мишкою, таку як клавіша, модифікатори тощо.

InputEventMouseMotion

Містить інформацію про рух, наприклад відносне й абсолютне положення та швидкість.

InputEventJoypadMotion

Містить інформацію про аналогову вісь Джойстика/Джойпада.

InputEventJoypadButton

Містить інформацію про джойстик/джойпад.

InputEventScreenTouch

Містить інформацію про натискання/відтискання кількох дотиків. (доступно тільки на мобільних пристроях)

InputEventScreenDrag

Містить відомості про переміщення кількох дотиків. (доступно тільки на мобільних пристроях)

InputEventMagnifyGesture

Містить позицію, фактор, а також модифікатори.

InputEventPanGesture

Містить позицію, дельту, а також модифікатори.

InputEventMIDI

Містить інформацію, пов'язану з MIDI.

InputEventShortcut

Містить ярлик.

InputEventAction

Містить загальну дію. Ці події часто генеруються програмістом як зворотний зв'язок. (Докладніше про це нижче)

Дії введення

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

Це дозволяє:

  • Один і той же код для роботи на різних пристроях з різними входами (наприклад, клавіатура на ПК, Joypad на консолі).

  • Вхід, який потрібно переналаштувати під час виконання.

  • Дії, які запускаються програмно під час виконання.

Дії можна створити в меню «Налаштування проекту» на вкладці Карта вхідних даних і призначити вхідні події.

Будь-яка подія має методи InputEvent.is_action(), InputEvent.is_pressed() і InputEvent.is_echo().

Крім того, може знадобитися надати грі дію з коду гри (хорошим прикладом цього є виявлення жестів). Синглтон Input має для цього метод: Input.parse_input_event(). Зазвичай ви використовуєте його так:

var ev = InputEventAction.new()
# Set as ui_left, pressed.
ev.action = "ui_left"
ev.pressed = true
# Feedback.
Input.parse_input_event(ev)

Дивись також

Дивіться Створення дій введення для підручника щодо додавання дій введення в налаштуваннях проекту.

InputMap (карта введення)

Часто бажано налаштувати та змінити вхідні дані з коду. Якщо весь ваш робочий процес залежить від дій, синглтон InputMap ідеально підходить для перепризначення або створення різних дій під час виконання. Цей синглтон не зберігається (потрібно змінити вручну), а його стан запускається з налаштувань проекту (project.godot). Таким чином, будь-яка динамічна система цього типу повинна зберігати налаштування у спосіб, який програміст вважає за потрібне.