Если коротко:
OpenXR Action Mapping связывает игровой смысл, например захват или телепорт, с вводом разных XR-контроллеров вместо проверки кнопки конкретной модели. В Unreal Engine OpenXR отвечает за действия и профили взаимодействия, а Enhanced Input организует контексты и обработку в игре. Привязки всё равно нужно проверять на каждом поддерживаемом устройстве вместе с позами и тактильной отдачей.
OpenXR Action Mapping Unreal Engine связывает игровой смысл — «схватить», «телепортироваться», «открыть меню» — с вводом разных XR-контроллеров. Приложение обращается к действию, а не опрашивает конкретную кнопку A или курок определённой модели. Такой слой не отменяет тестирование устройств, но уменьшает количество платформенных веток в логике.
В актуальных проектах Unreal Engine удобно разделить две задачи: OpenXR описывает XR-действия, позы и профили взаимодействия, а Enhanced Input организует контексты, триггеры и обработку внутри игры. Ошибка начинается, когда аппаратную кнопку, OpenXR action и игровую команду считают одним объектом.
Что такое action в OpenXR
Спецификация Khronos определяет action как именованное действие приложения. Оно может хранить:
- логическое состояние — нажато или нет;
- одномерное значение — например, ход курка;
- двумерное значение — положение стика;
- pose — положение и ориентацию руки;
- haptic output — команду вибрации.
Runtime сопоставляет действие с физическим источником ввода через interaction profile. Поэтому приложение запрашивает grab, а рекомендуемая привязка сообщает, какой элемент контроллера должен его вызвать.
Как разложить ввод на уровни
| Уровень | Пример | За что отвечает |
|---|---|---|
| Игровое действие | Grab, Teleport, Menu | смысл для механики |
| Input Action в Unreal | IA_Grab | тип значения и события |
| Mapping Context | IMC_VR | активный набор привязок |
| OpenXR binding | trigger/value | рекомендуемый физический источник |
| Interaction profile | Touch, Vive, Index | схема конкретного семейства контроллеров |
Если механика содержит проверку названия устройства, слои снова склеиваются. Лучше, чтобы компонент руки получал абстрактное действие и уже по нему запускал захват, интерфейс или телепортацию.
Подготовка проекта
- Включите OpenXR и необходимые расширения.
- Убедитесь, что лишний XR-плагин не перехватывает runtime без явной причины.
- Включите Enhanced Input.
- Создайте Input Actions для игровых команд.
- Создайте отдельный Input Mapping Context для VR.
- Подключайте контекст при активации VR-персонажа.
Общая настройка runtime и плагинов разобрана в статье OpenXR в Unreal Engine. Здесь предполагается, что проект уже запускается в гарнитуре и получает трекинг головы.
Какие Input Actions создать
Начните с минимального набора:
IA_GrabLeftиIA_GrabRight— Axis1D или Bool в зависимости от механики;IA_Teleport— Bool;IA_Move— Axis2D;IA_Turn— Axis2D;IA_Menu— Bool;IA_LeftPoseиIA_RightPose— позы рук обрабатываются XR-компонентами;- отдельные команды вибрации как выходные действия логики.
Левая и правая руки могут использовать общую функцию захвата, но источники ввода и состояние лучше не объединять в одну переменную. Иначе одновременное нажатие или потеря одного контроллера создают конфликт.
Input Mapping Context
Контекст задаёт, какие действия активны в конкретном режиме. Для VR полезно иметь основной IMC_VR, а поверх него подключать контексты интерфейса, транспорта или инструмента.
Приоритеты решают конфликт без ручного отключения десятков привязок. Например, в режиме меню стик может прокручивать список, а не перемещать персонажа. После закрытия меню контекст интерфейса снимается, и базовая локомоция снова получает ввод.
Привязка контроллеров через OpenXR
Назначайте действия семантически:
- захват — на squeeze или grip value;
- использование — на trigger value;
- меню — на доступную menu/system-подобную кнопку, если runtime разрешает;
- движение — на primary 2D axis;
- поворот — на secondary 2D axis;
- поза — на grip pose или aim pose в зависимости от задачи.
Grip pose обычно подходит для модели удерживаемого предмета. Aim pose удобнее для луча указателя или оружия. Подмена одной позы другой часто выглядит как неправильный угол контроллера, хотя трекинг работает корректно.
Почему нельзя жёстко проверять кнопку
Физическая кнопка на разных контроллерах может находиться в другом месте, отсутствовать или иметь иной смысл. Жёсткая проверка полезна только для платформенной функции, которая действительно принадлежит конкретному устройству.
Для общей механики используйте действие. Тогда новая схема добавляется в bindings, а Blueprint или C++-класс захвата остаётся прежним. Это соответствует модели OpenXR: runtime вправе выбрать доступный источник с учётом устройства и пользовательской конфигурации.
Как обрабатывать события Enhanced Input
У Input Action есть несколько стадий. Для VR особенно полезны:
- Started — начало нажатия или пересечение порога;
- Triggered — действие выполняется по правилам триггера;
- Completed — корректное завершение;
- Canceled — прерывание до выполнения.
Для захвата предмета обычно достаточно Started и Completed. Непрерывное значение курка читают в Triggered, если сила влияет на механику. Не запускайте создание объекта каждый кадр события Triggered без дополнительной защиты.
Порог аналогового захвата
Grip и trigger часто возвращают значение от 0 до 1. Если превращать любое ненулевое значение в нажатие, дрожание датчика вызывает повторные события. Добавьте порог и гистерезис: захват начинается при более высоком значении, а отпускается при более низком.
Точные числа выбирают на целевых контроллерах. Важен принцип: состояние не должно переключаться туда-обратно около одной границы.
Вибрация
Haptic action — выход, а не вход. Игровая логика решает, когда дать обратную связь, а XR-слой отправляет амплитуду и длительность доступному контроллеру.
Вибрация должна подтверждать событие: контакт, фиксацию, ошибку или отдачу. Постоянный сильный сигнал быстро утомляет и не переносится одинаково между устройствами. Проверяйте левую и правую руку отдельно.
Как тестировать bindings
Минимальная матрица проверки:
| Проверка | Левая рука | Правая рука | Второе устройство |
|---|---|---|---|
| grip pose | да | да | да |
| aim pose | да | да | да |
| захват и отпускание | да | да | да |
| стики и мёртвые зоны | да | да | да |
| меню | да | да | если доступно |
| вибрация | да | да | да |
Тестируйте packaged build, а не только Play in Editor. Runtime, активный профиль и разрешённые системные кнопки могут отличаться. Общий порядок проверки VR-проекта описан в чек-листе тестирования Unreal Engine.
Типичные ошибки
Действия не вызываются
Проверьте, добавлен ли Mapping Context в Enhanced Input Local Player Subsystem, активен ли нужный pawn и получает ли он ввод.
Кнопки работают, а позы нет
События кнопок и pose spaces — разные части системы. Проверьте Motion Controller Component, источник движения и выбранную grip/aim pose.
Работает только одна гарнитура
Ищите привязку к vendor-specific key, жёсткую проверку имени устройства или конфликт XR-плагинов. Оставляйте платформенную ветку только там, где общей возможности OpenXR недостаточно.
Левый контроллер управляет правой рукой
Проверьте hand/subaction path, отдельные компоненты рук и переменные состояния. Визуальная модель не должна определять источник ввода.
Архитектурный итог
Устойчивая схема выглядит так: физический контроллер → interaction profile → OpenXR binding → Input Action → Mapping Context → игровая функция. Каждый слой можно проверить отдельно. Тогда замена гарнитуры требует обновить привязки и тестовую матрицу, а не переписывать механику взаимодействия с объектами.