Архитектура объектов interactor — MRTK3

Одной из основ MRTK является набор объектов interactor, предлагаемых набором средств взаимодействия XR Unity. Для функций смешанной реальности, таких как отслеживание рук, взгляда и сжатия, необходимы более сложные объекты interactor, чем в наборе XRI по умолчанию. MRTK определяет новые интерфейсы объектов interactor, классифицируемые в основном по методам ввода и соответствующие реализации.

Сводка и обзор

Разработчикам, не знакомым с XRI, рекомендуется сначала ознакомиться с документацией по архитектуре XRI в Unity. Объекты interactor в MRTK — это подклассы существующих объектов interactor XRI или реализации интерфейсов interactor XRI. См. документацию по архитектуре объектов interactor Unity, которая также относится к MRTK.

Полноценные элементы XRI

Пользовательские объекты interactor MRTK соответствуют стандартным интерфейсам interactor XRI; с точки зрения систем XRI они неотличимы от стандартных объектов interactor. Это действительно и в обратном направлении: при создании расширенных интерактивных компонентов в MRTK стандартные объекты interactor XRI поддерживают базовые функции наведения указателя и выбора. Это соответствует принципам полной обратной совместимости MRTK с существующими проектами XRI. Если у вас есть приложение XRI, интерактивные объекты MRTK и элементы управления пользовательского интерфейса будут работать с вашей существующей стандартной конфигурацией XRI.

Абстракция метода ввода

Устройство ввода, объект interactor, выполняющий взаимодействие, и генерируемые ими события взаимодействия являются изолированными в XRI в архитектурном плане. Эта изоляция крайне важна с точки зрения стратегии абстракции ввода в MRTK3. Это позволяет нам разрабатывать взаимодействия для разных платформ и устройств, которые правильно функционируют во всех контекстах.

В MRTK 2 существуют общепринятые правила написания кода взаимодействий для определенного типов ввода или устройства. Многие разработчики привыкли создавать взаимодействия, которые реагируют именно на захват с ближнего расстояния, луч дальнего взаимодействия или другой определенный тип ввода.

Хотя в MRTK3 также можно различать и распознавать отдельные режимы ввода, жесткое кодирование взаимодействий для определенных типов ввода искусственным образом ограничивает возможности и снижает гибкость взаимодействий. Дополнительные сведения об этом можно найти в документации по архитектуре интерактивных элементов, но основным принципом для объектов interactor является то, что их, как правило, не нужно однозначно сопоставлять с конкретными устройствами ввода.

AttachTransform и обращение управления

За основную часть того, что в MRTK 2 было реализовано в "логике перемещения" в ObjectManipulator, Slider и т. д., теперь отвечает сам объект interactor. Теперь объект interactor управляет своим преобразованием attachTransform, которое определяет поведение определенного типа манипуляции. Вам больше не требуется писать сложную логику взаимодействия для интерактивного объекта для каждого метода ввода — вместо этого единая логика манипулирования может отслеживать позу attachTransform независимо от метода ввода или задействованного устройства.

Например, преобразование attachTransformGrabInteractor находится в точке захвата на руке или контроллере. Преобразование attachTransformXRRayInteractor находится в точке попадания в конце луча. Преобразование attachTransformCanvasProxyInteractorнаходится в точке щелчка мышью. Для всех этих разных объектов interactor интерактивный объект не обязан определять тип объекта interactor для выбора правильной реакции на манипуляции.

Интерактивный объект запрашивает attachTransform и может одинаковым образом обрабатывать каждый объект attachTransform независимо от типа объекта interactor.

Этот подход имеет решающее значение с точки зрения совместимости с существующими объектами interactor в XRI, а также задела на будущее при разработке взаимодействий для методов ввода, которых пока не существует. При появлении нового метода ввода вам не потребуется изменять существующие интерактивные объекты, если новый объект interactor создает допустимое и правильно функционирующее преобразование attachTransform.

Таким образом, с философской точки зрения преобразование attachTransformявляется логикой взаимодействия. Для любых пользовательских взаимодействий всегда рекомендуется создавать новый объект interactor с новой логикой attachTransform вместо того, чтобы переписывать или расширять интерактивные объекты с учетом особенностей нового взаимодействия. Таким образом, преимущества нового взаимодействия смогут использовать все существующие интерактивные объекты, а не только те, которые вы переписали или расширили.

XRControllers и привязка ввода

Большинство объектов interactor не привязываются к входным действиям напрямую. Как правило, они являются производными от XRBaseControllerInteractor, вследствие чего объект XRController должен находиться в иерархии выше объекта interactor. XRController привязывается к входным действиям, а затем распространяет соответствующие действия (выбор и т. д.) по всем присоединенным объектам interactor.

В то же время некоторым объектам interactor могут быть необходимы отдельные входные привязки или дополнительные входные данные, которые XRController не предоставляет. В таких случаях объекты interactor могут напрямую связываться с собственными уникальными входными действиями или даже использовать в логике взаимодействия другие (не относящиеся к системному вводу) источники. Базовые классы XRI обычно отслеживают привязки XRController, но это поведение можно переопределить в пользу работы с внешними или альтернативными источниками входных данных.

Интерфейсы

XRI определяет базовые объекты IXRInteractor, IXRHoverInteractor, IXRSelectInteractor и IXRActivateInteractor. MRTK определяет дополнительные интерфейсы для объектов interactor. Некоторые предоставляют дополнительные сведения о взаимодействиях MRTK, а другие предназначены просто для классификации и идентификации. Эти интерфейсы находятся в пакете Core, в то время как реализации находятся в других пакетах, включая Input.

Важно!

Хотя эти интерфейсы полезны, если требуется отфильтровать определенный тип взаимодействия, создавать в коде жесткие привязки взаимодействий к отслеживаемым интерфейсам не рекомендуется. В каждой ситуации всегда отдавайте предпочтение универсальным интерфейсам XRI isSelected и isHovered вместо интерфейсов, связанных с определенным взаимодействием.

В отсутствие реальной необходимости не следует ссылаться на конкретные реализации MRTK этих интерфейсов в интерактивных объектах. Во всех случаях рекомендуется ссылаться на интерфейсы. Если вы будете ссылаться на конкретные типы явным образом, ваши интерактивные объекты смогут работать только с текущими существующими типами. Ссылаясь только на интерфейсы, вы гарантируете совместимость с будущими реализациями, которые могут не являться подклассами существующих.

IVariableSelectInteractor

Объекты interactor, реализующие этот интерфейс, могут возвращать переменное (аналоговое) состояние выборки интерактивным элементам. Для запроса переменного объема выбора можно использовать свойство SelectProgress. Объекты interactor МРТК, реализующие этот интерфейс, включают MRTKRayInteractor и GazePinchInteractor. Переменный объем выбора не затрагивает базовые интерактивные объекты (интерактивные объекты XRI по умолчанию и MRTKBaseInteractable); при этом StatefulInteractable отслеживает это значение и вычисляет для него Selectedness на основе max() всех участвующих переменных и непеременных объектов interactor.

IGazeInteractor

Объекты interactor, реализующие этот интерфейс, представляют пассивный взгляд пользователя отдельно от любых манипуляций и намерений. Реализация MRTK представляет собой FuzzyGazeInteractor, являющийся наследником XRRayInteractor XRI, и добавляет логику приведения нечеткого конуса. XRBaseInteractable помечает IsGazeHovered при наведении указателя IGazeInteractor.

IGrabInteractor

Объекты interactor, реализующие этот интерфейс, представляют физическое взаимодействие ближнего захвата. attachTransform определяется как точка захвата. Реализация MRTK представляет собой GrabInteractor — подкласс XRDirectInteractor XRI.

IPokeInteractor

Объекты interactor, реализующие этот интерфейс, представляют взаимодействие касания. Обратите внимание, что это не обязательно касание пальцем! Этот интерфейс могут реализовывать произвольные объекты interactor, обеспечивающие взаимодействие касания из источников, не связанных с пальцами. В одном из немногих сценариев, в которых отслеживание интерфейсов взаимодействия имеет смысл, интерактивные элементы наподобие PressableButton отслеживают IPokeInteractor, например, на предмет объемного нажатия. Любой объект interactor, реализующий IPokeInteractor, инициирует трехмерные нажатия на кнопки.

IPokeInteractor предоставляет свойство PokeRadius, определяющее характеристики объекта, который инициирует касание. Касание считается сосредоточенным на attachTransform и простирается наружу от attachTransform на радиус PokeRadius. Интерактивные объекты, такие как PressableButton, смещают свое расстояние объемного нажатия на этот радиус, который в случае нажатия пальцем может определяться физической толщиной пальца пользователя.

Реализация MRTK этого интерфейса — PokeInteractor. В нашем проекте шаблона мы также предлагаем еще один пример IPokeInteractor, не связанный с управлением пальцем; PenInteractor обслуживает взаимодействия касания кончиком виртуального трехмерного пера.

IRayInteractor

Объекты interactor, реализующие этот интерфейс, представляют взаимодействие с помощью лучей. attachTransform представляет расположение попадания луча на поверхность целевого объекта во время выделения.

Реализация MRTK этого интерфейса — MRTKRayInteractor; она наследуется непосредственно от XRRayInteractor XRI.

Примечание

XRRayInteractor в XRI не реализует этот интерфейс MRTK.

ISpeechInteractor

Объекты interactor, реализующие этот интерфейс, представляют взаимодействие с использованием речи. В MRTK это реализация SpeechInteractor.

SpeechInteractor в MRTK внутренне использует PhraseRecognitionSubsystem и подписывается на события регистрации интерактивных объектов из XRInteractionManager XRI. При этом интерактивным объектам не нужно отслеживать подсистему, выполняющую обработку речи; ISpeechInteractor создают те же события XRI (выбор и т. д.), что и любой другой объект interactor.

IGazePinchInteractor

Этот интерфейс является простой специализацией интерфейса IVariableSelectInteractor. Объекты interactor, реализующие этот интерфейс, неявным образом являются объектами interactor переменного выбора. IGazePinchInteractor явным образом представляют косвенное целевое удаленное манипулирование. Отдельный объект interactor на основе взгляда управляет целью взаимодействия, а манипуляция выполняется рукой или контроллером. attachTransform работает так же, как и преобразование attachTransformIRayInteractor — привязывается к точке попадания на целевой объект при инициировании выбора.

Если несколько IGazePinchInteractor участвуют в одном взаимодействии, их преобразования attachTransform смещаются на соответствующие величины сдвига от медианной точки между всеми участвующими точками сжатия. Таким образом, интерактивные объекты могут интерпретировать эти attachTransformтак же, как и для любого другого многоручного взаимодействия, например attachTransforms взаимодействия захвата или взаимодействия с использованием лучей.

В MRTK это реализация GazePinchInteractor.

IHandedInteractor

Некоторые объекты interactor могут реализовать интерфейс IHandedInteractor, чтобы явным образом указать на свою связь с определенной рукой пользователя. Некоторые объекты interactor не связаны с руками и поэтому не реализуют его. Наиболее очевидные примеры — SpeechInteractor и FuzzyGazeInteractor.

Объекты interactor MRTK, реализующие этот интерфейс, представляют собой HandJointInteractor — универсальный абстрактный объект XRDirectInteractor, управляемый произвольным соединением рук, GazePinchInteractor и MRTKRayInteractor.

Интерактивные элементы в настоящее время используют его интерфейс для запуска определенных эффектов при выборе для идентификации левой и правой рук. Самым явным примером является эффект импульса в библиотеке компонентов пользовательского интерфейса.