Расширенный ввод
Плагин «Расширенный ввод» — это собственный плагин, созданный компанией Epic Games, который мы будем использовать в игре Parrot. Если вы используете последнюю версию Unreal Engine 5, плагин уже должен быть включён по умолчанию. Если необходимо, вы можете перейти в раздел Правка > Плагины и проверить, установлен ли соответствующий флажок.
Расширенный ввод заменяет стандартную систему ввода Unreal Engine и является стандартом для сложной обработки ввода или переназначения управления в среде выполнения. В официальной документации от Epic Games вы найдёте подробный разбор того, как устроена данная система и как настроить ресурсы ввода.
Основные понятия
Как уже указано в официальной документации, к основным концепциям расширенного ввода относится следующее:
Действия ввода.
Контексты назначений ввода.
Модификаторы ввода.
Триггеры ввода.
Если вы уже пользовались новой системой ввода в Unity, они скорее всего покажутся вам знакомыми.
Действия ввода лучше всего рассматривать как действия, выполняемые в игре в рамках конкретного контекста. Например, если персонаж едет на машине, нужно иметь действия «Газ» и «Тормоз».
Контексты назначений ввода также можно рассмотреть на следующем примере. Если игрок входит или выходит из машины, вы можете изменить действие определённых клавиш или кнопок геймпада.
Триггеры ввода будут блокировать действия срабатывания, если будут выполнены не все условия. К примеру, вы можете сделать так, чтобы действие срабатывало только после удержания кнопки в течение определённого периода времени.
Модификаторы ввода используются для изменения значения самого ввода. Так называемые «мёртвые зоны» — это один из наиболее распространённых примеров модификации ввода для обеспечения большей плавности необработанным значениям ввода. Расширенный ввод позволяет решить все эти проблемы с помощью некоторых настроек.
Разберём один из примеров из игры Parrot. По пути Содержимое/Input/Gameplay вы сможете найти папку Actions, а также файл ресурсов IMC_Gameplay. В папке Actions найдите ресурс IA_Jump.
Тип значения в данном случае будет цифровой (логический), что указывает на тип вывода этого действия. Для триггеров предусмотрены следующие типы:
при нажатии;
при отпускании.
Если взглянуть на это действие ввода, несложно догадаться, что любая клавиша или кнопка должна срабатывать по нажатию и иметь логическое состояние вывода. Отпускание кнопки приводит к завершению действия. Ещё одна важная деталь: и триггеры, и модификаторы можно переопределить с помощью контекста назначений ввода. Давайте рассмотрим контекст назначений ввода в игровом процессе и разберёмся в том, как работает переопределение модификаторов на практике.
У IA_MoveAxis нет заданного триггера, поэтому значение по оси X левого стика геймпада здесь будет считываться сразу при обнаружении изменения. Чтобы добиться более плавного перемещения, мы используем модификатор мёртвой зоны и задаём верхнюю и нижнюю границы данных ввода.
Примером, когда мы не выполняем переопределение в контексте назначения ввода, является назначение для прыжков.
Здесь вы можете заметить, что триггер привязан непосредственно к действию ввода, поэтому нет необходимости задавать триггер для назначения. Настройки также наследуются от действия, но на это вы можете пока не обращать внимания, так как мы рассмотрим это позже, в разделе, посвящённом переназначениям.
Слушатели событий расширенного ввода
Теперь, когда ваши ресурсы подготовлены, необходимо выполнить настройку для использования в среде выполнения. В игре Parrot мы выполняем привязку к подсистеме расширенного ввода для локального игрока, чтобы настроить слушателей событий в BP_ParrotPlayerController. От узла BeginPlay мы добавляем контекст назначений для IMC_Gameplay.
Здесь важен параметр приоритета. Контексты назначения ввода оцениваются по их приоритету: важно учитывать это при наложении контекстов. Пока мы будем использовать только контекст игрового процесса.
Обратите внимание, что для параметра Настройки уведомления пользователя установлено значение true — это будет необходимо для переназначения ввода в среде выполнения позже.
После того, как контекст назначения будет готов, останется только добавить узлы событий расширенного ввода для желаемых действий. Вот пример прыжка:
Действие начинается, когда игрок нажимает на кнопку, и завершается, когда кнопка отпускается. Обратите внимание на остальные действия ввода в BP_ParrotPlayerController, чтобы увидеть, как обрабатываются другие типы ввода. При необходимости вы можете привязать события ввода на C++: это подробнее описано в официальной документации.
Переназначение ввода в среде выполнения
С помощью расширенного ввода предусмотрена возможность переназначать клавиши, привязанные к действиям ввода, в среде выполнения. Стоит отметить, что хоть эта функция и работает, она все ещё находится на экспериментальной стадии, поэтому использовать её в готовых проектах следует с осторожностью. В игре Parrot есть экран назначений клавиш, который позволяет игроку переназначать используемые кнопки или клавиши. Здесь возможности расширенного ввода мы будем использовать вместе с плагином CommonUI от Epic Games: это позволит обеспечить корректные метаданные для экранных виджетов. Настройка CommonUI описана в разделе документации «Пользовательский интерфейс»: рекомендуем ознакомиться с ним, прежде чем приступать к дальнейшим шагам. Установив плагин, вы также сможете отображать элементы интерфейса с учётом конкретной платформы, на которой запускается проект.
Сначала в настройках проекта необходимо активировать параметр «Пользовательские настройки» для расширенного ввода. Найти его вы можете в разделе Правка > Настройки проекта > Движок > Расширенный ввод. Выставьте следующие параметры
Далее перейдите к ресурсу действия ввода и задайте Настройки назначаемых клавиш игрока. Значение поля Название должно быть уникальным и не повторяться среди всех ваших действий ввода. Поля Отображаемое название и Категория в игре Parrot локализованы.
Вы также можете переопределить настройки отображаемых клавиш игрока при определении клавиши в контексте назначений ввода. Для действия прыжка в контексте назначений ввода игрового процесса остаётся настройка «Наследовать настройки от действия», поэтому здесь больше ничего не требуется.
Обязательно проверьте, чтобы при добавлении контекста назначений ввода на схеме контроллера игрока параметр Настройки уведомления пользователя имел значение true.
В следующей части мы рассмотрим, как связать действия расширенного ввода с CommonUI. Мы разберём, что требуется для переназначения ввода в игре Parrot, при этом данная документация является дополнением к официальному базовому руководству по CommonUI.
Для следующего шага мы создали новый контекст назначений ввода IMC_UI_Generic по пути Содержимое/Input/UI.
Необходимо задать поле «Настройки назначаемых клавиш игрока» для каждого действия ввода с указанием на соответствующий ресурс данных метаданных интерфейса. Рассмотрим пример стандартного действия ввода «Принять» и соответствующего ресурса метаданных.
Этот контекст назначений ввода, а также действия ввода необходимы для того, чтобы плагину CommonUI было известно о действиях, вызываемых навигацией по интерфейсу. Стандартные действия ввода «Принять» и «Назад» являются здесь основными примерами, поскольку игрок будет часто пользоваться ими при навигации по разделам интерфейса. Мы определяем эти назначения в конкретной схеме данных CommonUI, являющейся подклассом CommonUIInputData.
Далее, в разделе Правка > Настройки проекта > Общие настройки ввода, задайте для данных ввода вашу схему для стандартных данных ввода.
Когда важные поля настроены, можно приступить к настройке экранов виджетов. Начнём с использования базового класса Parrot Screen для статичных экранов и активируемого класса — для остальных. Статичные экраны — это что-то вроде HUD-интерфейса, где не нужно продумывать навигацию. Примером активируемого класса может служить меню паузы, поскольку ему необходимо знать, когда нажата кнопка «Назад», при этом оно существует на слое основного меню компоновки игры.
Иерархия экранов более подробно описана в разделе документации «Пользовательский интерфейс», но для справки мы повторим эту информацию и здесь:
В настройках класса по умолчанию для экранов схем Blueprint мы задаём необязательный контекст назначений ввода. Это будет применяться при активации/деактивации виджета, при этом вы можете выполнить переопределение для каждого класса.
У UParrotActivatableScreen имеется реализация для обработки действий перехода назад. Слушатель событий IA_UI_GenericBack определён в графе событий производных схем, которые его используют. Также необходимо установить флажок для параметра Является обработчиком действия перехода назад (Is Back Handler) на панели «Сведения».
Рекомендуем ознакомиться с комментариями в классе C++ и в схеме, чтобы разобраться, как шаблон перехода назад используется в различных экранных виджетах.
Ознакомившись с базовыми классами, перейдите в раздел привязки клавиш. WBP_KeyBindingsScreen находится по пути Содержимое/UI/Widgets/Screens. С графом событий рекомендуем ознакомиться самостоятельно, чтобы узнать, каким образом запрашиваются Пользовательские настройки и Профили клавиш для получения типов Назначений клавиш игрока из расширенного ввода. Данные используются для добавления и заполнения виджетов WBP_InputSelectorBox. Внутри виджета WBP_InputSelectorBox вы можете увидеть два виджета W_ParrotInputSelector.
Один используется для ввода с геймпада, другой — для ввода с клавиатуры. Селектор ввода в игре Parrot — это пользовательский виджет, за основу которого взят встроенный виджет селектора ввода. Оба этих виджета переходят в состояние выбора, ожидают ввода и затем обновляют отображаемые данные:
В случае мыши и клавиатуры мы работаем с возвращаемым текстом из подсистемы расширенного ввода и обновляем отображаемые данные.
Обработка ввода с геймпада уже задействует CommonUI для запроса изображений для конкретного контроллера. В данном случае мы подготавливаем виджет для изображений Xbox с названием
CommonInput_Gamepad_Xboxпо путиСодержимое/Input/UI/Platform. Этот класс наследуется отUCommonInputBaseControllerData.
Производные от этого класса позволяют сопоставлять клавиши ввода с кистями с изображениями. Далее подготовим данные контроллера в разделе Правка > Настройки проекта > Общие настройки ввода и перейдём к платформе.
После подключения этих данных вся остальная работа выполняется уже внутри виджетов. Рекомендуем ознакомиться с кодом и комментариями в UParrotInputSelector и WBP_InputSelectorBox: это поможет разобраться, как работает система переназначения при помощи подсистем CommonUI и расширенного ввода.
Важно также обратить внимание на то, как выполняется сохранение назначенных клавиш или кнопок. Выполняется это в SaveKeyMappings в WBP_KeyBindingsScreen. Эта функция перебирает все виджеты поля селектора, а затем использует встроенные в пользовательские настройки функции Применить настройки и Сохранить настройки. Функция Сохранить настройки записывает файл сохранения игры EnhancedInputUserSettings.sav на диск. Его можно найти по пути Каталог проекта > Parrot > Saved-SaveGames.
Если всё было настроено правильно, у вас должен появиться работающий экран переназначения клавиш и кнопок!
Как вы могли заметить, в правом нижнем углу находится виджет действия, который обновляется при переназначении клавиши или кнопки. Этот виджет называется WBP_ParrotGamepadActionWidget, а найти его можно в разделе Содержимое/UI/Widgeвиджетs/Common. В нём активно используется класс UCommonActionWidget из CommonUI, который создан для отображения значков конкретных платформ при выполнении действия ввода за счёт использования общих данных ввода, которые мы задали ранее. Используя CommonUI, можно с лёгкостью создавать новые виджеты, которые будут ссылаться на действия расширенного ввода в вашей игре.