reckfellENGINE

Карта действий OpenXR: настройка ввода

Наборы, действия, профили контроллеров, рабочая карта на C# и диагностика привязок.

На этой странице

Карта действий связывает смысл ввода с элементами XR-контроллера. В игре проверяется действие select, а карта определяет, какая кнопка его вызывает на каждом профиле устройства. Это отдельная система от обычного InputMap: добавление действия в Project Settings → Input Map не создаёт привязку OpenXR.

Из чего состоит карта

РесурсНазначениеПример
OpenXRActionMapКорневой ресурс картыopenxr_action_map.rdata
OpenXRActionSetГруппа действий одного режима игрыgameplay, menu
OpenXRActionИменованное действие и тип его значенияselect, Bool
OpenXRInteractionProfileПривязки для профиля контроллера/interaction_profiles/khr/simple_controller
OpenXRIPBindingОдно действие и один полный путь ввода/user/hand/right/input/select/click

Внутреннее имя хранится в ResourceName; LocalizedName — подпись для человека. Делайте внутренние имена короткими, стабильными, строчными, например select или move_player. Не используйте перевод подписи как ключ в игровом коде. Имена действий внутри набора и их подписи не должны дублироваться: это проверяет XR runtime при создании действий. Требования OpenXR к имени и subaction paths.

ToplevelPaths задаёт устройства, для которых существует действие, например левую и правую руки. BindingPath задаёт конкретный элемент такого устройства. Для двух рук создаются две привязки к одному действию; строка с двумя путями через запятую не нужна.

Начните с одного действия

Минимальная карта для выбора предмета:

  1. Создайте набор gameplay, подпись Gameplay, Priority=0.
  2. Добавьте действие select, подпись Select, тип Bool.
  3. Укажите ToplevelPaths: /user/hand/left и /user/hand/right.
  4. Добавьте профиль /interaction_profiles/khr/simple_controller.
  5. Добавьте две привязки к select: /user/hand/left/input/select/click и /user/hand/right/input/select/click.
  6. Сохраните карту в asset://openxr_action_map.rdata.

Simple Controller описывает минимальный набор ввода. Он не предоставляет стики, все особенности конкретного контроллера или гарантию поддержки любой гарнитурой. Для дополнительного ввода добавляйте соответствующие профили и допустимые для них пути. Привязки приложения являются предложениями runtime, а не прямым доступом к сырым кнопкам. Правила предложенных привязок OpenXR.

Создание той же карты на C#

Этот вспомогательный класс создаёт ресурс и умеет сохранить его. Это не Entity-скрипт для прикрепления к объекту и не код запуска XR-сеанса.

C#
using Reckfell;

public static class SelectionActionMap
{
    // Caller owns the map. This builds resources; it does not start an XR session.
    public static OpenXRActionMap Create()
    {
        var map = new OpenXRActionMap();
        using var set = new OpenXRActionSet
        {
            ResourceName = "gameplay", LocalizedName = "Gameplay", Priority = 0
        };
        using var select = new OpenXRAction
        {
            ResourceName = "select", LocalizedName = "Select",
            ActionType = OpenXRAction.ActionTypeEnum.Bool,
            ToplevelPaths = ["/user/hand/left", "/user/hand/right"]
        };
        set.AddAction(select);
        map.AddActionSet(set);

        using var profile = new OpenXRInteractionProfile
        {
            InteractionProfilePath = "/interaction_profiles/khr/simple_controller"
        };
        using var left = new OpenXRIPBinding
        {
            Action = select, BindingPath = "/user/hand/left/input/select/click"
        };
        using var right = new OpenXRIPBinding
        {
            Action = select, BindingPath = "/user/hand/right/input/select/click"
        };
        using var bindings = new Reckfell.Collections.Array { left, right };
        profile.Bindings = bindings;
        map.AddInteractionProfile(profile);
        return map;
    }

    public static Error Save(string path = "asset://openxr_action_map.rdata")
    {
        using var map = Create();
        return ResourceSaver.Save(map, path);
    }
}

Из отдельного инструмента подготовки ресурсов вызовите SelectionActionMap.Save() и проверьте Error.Ok. По умолчанию файл будет записан в asset://openxr_action_map.rdata проекта, где выполнен вызов. Сначала подготовьте файл, затем запускайте XR-проект. Сохранение новой карты в _Ready() уже запущенного XR-сеанса не переподключает текущие действия.

В редакторе та же структура редактируется в доке OpenXR Action Map. Включите xr/openxr/enabled и перезапустите редактор при требовании перезапуска. Параметр xr/openxr/default_action_map должен указывать на нужный файл; его исходное значение — asset://openxr_action_map.rdata. Этот путь важнее совпадения имени файла с примером.

При отсутствии загружаемой карты native-код создаёт стандартную. В сборке с инструментами он также пытается сохранить её. Не рассчитывайте на автоматическое создание нужных игровых действий в экспортированном проекте: храните собственную карту в проекте и проверьте её попадание в экспорт.

Как читать действие

У XRController3D выберите tracker соответствующей руки: left_hand или right_hand. После успешного запуска и фокуса XR-сеанса опрашивайте действие по внутреннему имени:

Тип действияC#-метод XRController3DЧто означает
BoolIsButtonPressed("select")Состояние нажатия, не отдельное событие одного кадра
FloatGetFloat("trigger")Аналоговое значение настроенного действия
Vector2GetVector2("move")Две оси настроенного действия
PoseСвойство Pose у XR-объектаВыбор именованной отслеживаемой позы, не кнопка

trigger, move и нужную позу необходимо сначала определить и привязать; минимальная карта выше содержит только select. Она не заменяет настройку XROrigin3D, камеры и запуска XR.

В редакторе карты существует тип Haptic. Однако в текущем установленном C# SDK у OpenXRAction.ActionTypeEnum нет именованного Haptic: не используйте несуществующий член и не подставляйте числовой cast. Настройте такое действие в редакторе карты. Оно должно ссылаться на поддерживаемый выход, например /user/hand/right/output/haptic, прежде чем вызывать TriggerHapticPulse. Длительность этого вызова задаётся в секундах; Duration у OpenXRHapticVibration для модификаторов — в наносекундах. Наличие binding не подтверждает работу вибрации на устройстве.

Наборы и изменение карты

Для первого проекта оставьте один набор. Позже разделяйте gameplay и menu, если один элемент контроллера должен выполнять разные задачи. Активность переключается через OpenXRInterface.SetActionSetActive по имени существующего набора. Priority определяет разрешение конфликтов активных наборов; не оставляйте конфликтующие наборы активными без необходимости. Добавление OpenXRAction во второй OpenXRActionSet переносит его из первого: для независимых действий нужны разные ресурсы.

Не меняйте исходные ресурсы в надежде перестроить уже подключённый XR-сеанс. После подключения наборов OpenXR запрещает добавлять действия и менять предложенные привязки для этого сеанса. Подготовьте карту и перезапустите сеанс. Переключение активности существующих наборов — отдельная операция. Ограничения xrAttachSessionActionSets.

GetActionSets() в текущей реализации возвращает общий Array. Его Clear() изменяет карту без Changed. Для обычного редактирования пользуйтесь AddActionSet/RemoveActionSet и соответствующими методами ресурсов; не очищайте возвращённый контейнер как будто это независимая копия.

Модификаторы добавляйте после проверки базового ввода. Параметры xr/openxr/binding_modifiers/analog_threshold и xr/openxr/binding_modifiers/dpad_binding запрашивают соответствующие расширения; поддержка зависит от runtime. Для аналогового порога разделяйте порог включения и выключения, чтобы избежать дребезга около границы. D-pad предназначен для подходящего двумерного ввода, а не произвольного пути. Каждый модификатор нужно проверить на целевом runtime: сохранение ресурса не подтверждает его применение устройством.

Если действие не работает

СимптомПроверка
В коде всегда falseXR-сеанс запущен и имеет фокус; выбран правильный tracker; набор активен
Работает только одна рукаЕсть обе ToplevelPaths и отдельный BindingPath для каждой руки
Карта сохранена, но изменений нетСовпадает xr/openxr/default_action_map; сеанс перезапущен после сохранения
Не работает только на другом контроллереДобавлен нужный interaction profile; путь допустим для него; runtime принял bindings
Ошибка создания actionНет пустых/повторных имён и подписей; тип действия подходит пути
Не работает вибрацияЕсть выходное действие Haptic и нужный output-путь; передано верное имя и tracker; единицы длительности верны

В установленном движке без гарнитуры проверены точный C#-пример, структура, ссылки двух привязок на одно действие, сохранение .rdata и независимая повторная загрузка. Также проверены перенос действия между наборами и общая природа Array. Физический ввод, фокус сеанса, pose tracking, haptics, модификаторы и редакторские действия этим прогоном не проверялись.

Документация Reckfell EngineНаверх ↑
БЫСТРЫЙ ПЕРЕХОДНачало работыEntity и иерархияC# & .NET 10Сцены и префабы
Руководства и полный API Reckfell K
reckfellENGINE
RECKFELL ACCOUNT

Вход в аккаунт

Войдите в аккаунт Reckfell.

Один аккаунт для всей платформы Reckfell.