Меню руки — MRTK3

Hand Menu

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

Меню "Рука" предоставляет параметры "Требовать неструктурированные руки" и "Использовать активацию взгляда", чтобы предотвратить ложную активацию при взаимодействии с другими объектами. Рекомендуется использовать эти параметры для предотвращения нежелательной активации.

Пример сцены и prefabs

Примечание

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

Если вы используете проект шаблона, HandMenuExamples.unity демонстрирует несколько распространенных конфигураций для меню рук, все с помощью скрипта HandConstraintPalmUp .

Hand Menu Example Scene

HandMenu1x4 и HandMenu2x4

Меню становится видимым и невидимым в этих префабах путем активации и деактивации объекта MenuContent в событиях OnFirstHandDetected() и OnLastHandLost(). Это поведение рекомендуется для меню с небольшим пользовательским интерфейсом, для которого требуется короткий промежуток времени взаимодействия.

Hand Menu Example 2x4

HandMenuLarge

Этот префаб демонстрирует пример большого или сложного пользовательского интерфейса, требующего длительного времени взаимодействия. Для этого типа пользовательского интерфейса рекомендуется заблокировать меню в раскрывающемся меню, чтобы повысить удобство использования и избежать усталости рук. В этом примере также поддерживается "захват и извлечение" для блокировки меню.

В этом примере меню становится видимым и невидимым путем активации объекта MenuContent в событии OnFirstHandDetected(). При возникновении события OnLastHandLost() активируется кнопка закрытия и активируется анимация размещения. Анимация — это простое изменение масштаба. Так как мы не скрывали событие MenuContent в OnLastHandLost(), меню будет автоматически заблокировано, когда рука не видна. Значения в разделе Palm Up были оптимизированы, чтобы сделать меню заблокированным миром, не перетаскивая вниз слишком много при перетаскивании рук.

Hand Menu Example Large 1

Palm Up configuration

В этом примере показана полоса захвата в нижней области меню и автоматическое поведение блокировки мира. Пользователь может явно отсоединить меню от руки и поместить его в мир, захватив это. Для этого при выполнении события ManipulationStarted() в ObjectManipulator мы отключаем SolverHandler.UpdateSolvers. В противном случае меню не сможет быть отсоединяться, так как решатель HandConstraint попытается разместить меню рядом с положением руки. Мы также используем HandConstraintPalmUp.StartWorldLockReattachCheckCoroutine , чтобы позволить пользователю поднять руку, чтобы повторно подключить меню к руке.

Hand Menu Example Large 2

Наконец, кнопка закрытия должна повторно активировать solverHandler.UpdateSolvers для восстановления функциональности решателя HandConstraint.

Hand Menu Example Large 3

Скрипты

Поведение HandConstraint предоставляет решателя, который ограничивает отслеживаемый объект регионом, безопасным для содержимого, ограничиваемого руками (например, пользовательского интерфейса руки, меню и т. д.). Безопасные регионы считаются областями, которые не пересекаются с рукой. Производный класс HandConstraint, вызываемый HandConstraintPalmUp, также включен для демонстрации общего поведения активации объекта, отслеживаемого решателем, когда ладонь обращена к пользователю.

Дополнительные сведения см. в подсказках, доступных для каждого HandConstraint свойства. Ниже описано несколько свойств.

  • Сейф зона: безопасная зона указывает, где на руке ограничивается содержимое. Рекомендуется размещать содержимое на стороне Ulnar, чтобы избежать перекрытия с рукой и улучшенного качества взаимодействия. Сейф зоны вычисляются ориентацией рук, проецируемыми в плоскость ортогональной для просмотра камеры и лучами по ограничивающей коробке вокруг рук. Сейф зоны определяются для работы с XRNode. Рекомендуется изучить, какие типы контроллеров представляют каждую безопасную зону.

  • Следите за рукой, пока не Камера С этим активным, решатель будет следовать повороту руки, пока меню не будет достаточно выровнено с взглядом, когда он сталкивается с камерой. Чтобы сделать эту работу, измените SolverRotationBehavior значение в HandConstraintSolverэлементе , начиная с GazeAlignmentLookAtTrackedObjectLookAtMainCamera угла с решателем.

Hand Menu Example Safe Zone

  • События активации: в настоящее HandConstraint время триггеры четыре события активации. Эти события можно использовать во многих различных сочетаниях для создания уникальных HandConstraint поведений.

    • OnHandActivate: активирует, когда рука удовлетворяет методу IsHandActive.
    • OnHandDeactivate: активирует, когда метод IsHandActive больше не удовлетворяется.
    • OnFirstHandDetected: происходит, когда состояние отслеживания рук не меняется с рук в виду на первую руку.
    • OnLastHandLost: возникает, когда состояние отслеживания рук изменяется по крайней мере с одной руки в виду на отсутствие рук в представлении.
  • Логика активации и деактивации решения. В настоящее время рекомендуется активировать и деактивировать HandConstraintPalmUp логику, SolverHandlerиспользуя значение вместо UpdateSolver отключения или включения объекта. Это можно увидеть в примере сцены с помощью обработчиков на основе редактора, запускаемых после событий ManipulationHandler вложенного меню OnManipulationStarted/Ended.

    • Остановка логики ограничения рук: при попытке остановить объект с ограниченными руками (а не запустить логику активации или деактивации), установите для UpdateSolver значение False, а не отключает HandConstraintPalmUp.
      • Если вы хотите включить логику повторного подключения на основе взгляда (или даже не на основе взгляда), то за ней следует вызов HandConstraintPalmUp.StartWorldLockReattachCheckCoroutine() функции. Это вызовет сопрограмму, которая продолжает проверять, выполнены ли критерии "IsValidController" и присвоит UpdateSolver значение True после того, как он будет (или объект отключен).
    • Запуск логики ограничения руки: при попытке задать объект с ограниченными ручными руками, чтобы начать выполняться снова (в зависимости от того, соответствует ли он условиям активации), задайте для объекта SolverHandler в UpdateSolver значение true.
  • Логика повторного подключения: в настоящее время можно автоматически повторно подключить целевой объект к отслеживаемой точке независимо от того, HandConstraintPalmUp имеет ли SolverHandlerзначение true UpdateSolver . Это делается путем вызова HandConstraintPalmUpStartWorldLockReattachCheckCoroutine() функции после того, как она была заблокирована в мире (в данном случае фактически устанавливает UpdateSolver в SolverHandler значение False).