Если коротко:
Enhanced Input отделяет игровое действие от конкретной кнопки VR-контроллера. Разработчик создаёт Input Action, добавляет его в Mapping Context, назначает OpenXR-ввод и подключает контекст к локальному игроку. Такая структура позволяет менять схемы для интерфейса и инструментов, а проблемы диагностировать последовательно на уровне контекста, действия и профиля контроллера.
Enhanced Input для VR в Unreal Engine отделяет намерение пользователя от физической кнопки. Действие «схватить» можно связать с Grip разных контроллеров, поворот — с осью стика, а меню — с отдельными профилями OpenXR. Проект оперирует Input Actions и Mapping Contexts, а не разбросанными проверками клавиш в каждом Blueprint.
Базовая цепочка такова: создать Input Action, добавить её в Input Mapping Context, назначить XR-кнопки или оси, подключить контекст к локальному игроку и обработать событие в Pawn или Controller. OpenXR сопоставляет действия с interaction profile подключённого устройства.
Из чего состоит Enhanced Input
Input Action описывает смысл действия и тип значения. Кнопка захвата обычно использует Boolean, положение стика — Axis2D, аналоговый курок — Axis1D. Один ассет может вызывать разные обработчики без привязки логики к конкретной модели контроллера.
Input Mapping Context хранит набор соответствий между действиями и физическим вводом. Контексты можно добавлять и удалять во время выполнения, а приоритет решает конфликт. Например, общий VR-контекст отвечает за руки и перемещение, а контекст меню временно переназначает стик на навигацию по интерфейсу.
Modifiers преобразуют входное значение: инвертируют ось, меняют порядок компонентов, применяют dead zone или масштаб. Triggers определяют условие срабатывания: нажатие, удержание, отпускание, порог либо комбинация.
Минимальная структура VR-проекта
Создайте отдельные действия:
IA_GrabLeftиIA_GrabRight— захват;IA_Move— двумерная ось перемещения;IA_Turn— горизонтальная ось поворота;IA_Teleport— подготовка и подтверждение телепорта;IA_Menu— открытие системного меню приложения.
Затем создайте IMC_VR_Default и свяжите действия с ключами OpenXR для левой и правой руки. Разделение захвата по рукам упрощает обращение к Motion Controller Component. Симметричное действие допустимо, если обработчик получает контекст руки другим надёжным способом.
Не помещайте бизнес-логику внутрь Mapping Context. Контекст должен отвечать на вопрос «какой ввод вызывает действие», а Pawn и компоненты взаимодействия — «что происходит после действия».
Подключение Mapping Context
В Blueprint после получения Player Controller найдите Enhanced Input Local Player Subsystem и вызовите Add Mapping Context. Обычно это делают в BeginPlay управляемого Pawn или после подтверждения, что локальный игрок создан.
Передайте IMC_VR_Default и приоритет. Значение приоритета важно только относительно других активных контекстов. Для меню можно добавить контекст с более высоким приоритетом, а при закрытии удалить его.
Если событие Input Action не приходит, проверьте по порядку:
- Enhanced Input включён и используется проектом.
- Pawn действительно принадлежит локальному Player Controller.
- Mapping Context добавлен в Local Player Subsystem.
- В контексте есть назначение для ожидаемого XR-ключа.
- OpenXR runtime видит контроллер и активный interaction profile.
- Интерфейс или другой контекст не перехватывает действие с большим приоритетом.
Как связать Enhanced Input с OpenXR
OpenXR описывает действия и профили взаимодействия разных контроллеров. Unreal использует Action Mapping System, чтобы сформировать привязки для runtime. По документации Epic, если проект явно назначил часть действий конкретному контроллеру, отсутствующие назначения могут не эмулироваться автоматически.
Поэтому поддержка устройства должна быть полной: если добавили профиль контроллера, назначьте все обязательные действия, а не только Jump или Grab. Проверяйте минимум два разных семейства контроллеров, если заявляете кроссплатформенность.
Не смешивайте без необходимости старые абстрактные Motion Controller keys, vendor-specific ввод и OpenXR-действия. В проектах после миграции такая смесь создаёт двойные события и разные результаты на Quest, Vive или Index.
Захват предмета
Событие Started удобно для начала захвата, Completed — для отпускания. Если требуется учитывать силу аналогового Grip, используйте Axis1D и читайте значение во время Triggered.
Обработчик не должен каждый кадр искать все предметы в сцене. Motion Controller Component может поддерживать небольшой список объектов в зоне взаимодействия, а при нажатии выбирается ближайший допустимый кандидат. Правила захвата лучше вынести в интерфейс или компонент, чтобы дверь, инструмент и свободный объект не копировали одну схему Blueprint.
Для двух рук определите поведение заранее: может ли вторая рука перехватить объект, становится ли она дополнительной точкой удержания и кто получает событие Release. Ошибки здесь часто принимают за сбой ввода, хотя событие пришло корректно.
Перемещение и поворот
Для стика используйте Axis2D. Один компонент отвечает за движение вперёд и вбок, второй — за поворот. В snap turn действие должно срабатывать один раз при пересечении порога и ждать возврата стика в нейтральную зону. Иначе один наклон вызывает серию рывков.
Dead zone лучше задавать Modifier в Mapping Context. Тогда код локомоции получает уже очищенное значение. Порог поворота можно оформить Trigger, а угол — параметром компонента движения.
У плавного поворота и телепорта разные требования к комфорту, поэтому их удобно держать в отдельных контекстах или настройках. Подробнее архитектура перемещения разобрана в материале о локомоции в Unreal Engine.
Контексты для интерфейса и инструментов
Когда открыто меню, пользователь может продолжать держать предмет. Простое добавление нового контекста не всегда отключает старый. Решите явно, какие действия должны оставаться: системный выход, положение рук и указатель обычно нужны, перемещение — часто нет.
Для инструмента можно добавить временный контекст: курок включает распылитель, кнопка A меняет режим, стик регулирует параметр. После отпускания инструмента контекст удаляется. Такой подход чище, чем один глобальный Mapping Context с сотнями назначений.
Диагностика
Выводите имя Action, фазу Trigger Event, значение и активную руку на экран или в лог. Отдельно фиксируйте подключённый runtime и модель interaction profile. Это позволяет разделить четыре класса ошибок: устройство не обнаружено, неверная привязка, контекст не активен, игровая логика отвергла действие.
Для трудно воспроизводимой ошибки сохраните видео с контроллерами в кадре и синхронный лог событий: так видно, произошло ли физическое нажатие до изменения состояния в Blueprint.
Тестируйте Started, Triggered, Ongoing, Completed и Canceled. Для кнопки чаще достаточно начала и завершения, а непрерывная ось требует Triggered. Если логика выполняется дважды, ищите дублирующий Mapping Context или старую привязку.
Enhanced Input не заменяет OpenXR и не гарантирует поддержку каждого контроллера сам по себе. Он создаёт управляемый слой действий. Надёжность появляется, когда команда хранит контексты по сценариям, полностью заполняет заявленные профили и проверяет события на реальных устройствах.