Контроллеры, указатели и фокус — MRTK2

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

Контроллеры

Контроллеры — это представления физического контроллера (6-степеней свободы, рук с четкой формулировкой и т. д.). Они создаются диспетчерами устройств и отвечают за взаимодействие с соответствующей базовой системой и преобразование данных в данные и события в формате MRTK.

Например, на платформе Windows Mixed Reality является контроллером, WindowsMixedRealityArticulatedHand который отвечает за взаимодействие с базовыми API отслеживания рук Windows для получения сведений о суставах, позе и других свойствах руки. Он отвечает за преобразование этих данных в соответствующие события MRTK (например, путем вызова RaisePoseInputChanged или RaiseHandJointsUpdated) и обновления собственного внутреннего состояния таким образом, чтобы запросы для TryGetJointPose возвращали правильные данные.

Как правило, жизненный цикл контроллера включает в себя:

  1. Контроллер создается диспетчером устройств при обнаружении нового источника (например, диспетчер устройств обнаруживает и начинает отслеживать руку).

  2. В цикле Update() контроллера он вызывает базовую систему API.

  3. В том же цикле обновления он вызывает изменения событий ввода, вызывая непосредственно в основную систему ввода (например, вызов HandMeshUpdated или HandJointsUpdated).

Указатели и фокус

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

Категории указателей

Указатели обычно делятся на одну из следующих категорий:

  • Дальние указатели

    Эти типы указателей используются для взаимодействия с объектами, которые находятся далеко от пользователя (далеко определяется как просто "не рядом"). Эти типы указателей обычно прививывают линии, которые могут идти далеко в мир и позволяют пользователю взаимодействовать с объектами, которые не находятся непосредственно рядом с ними, и управлять ими.

  • Ближайшие указатели

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

  • Указатели телепорта

    Эти типы указателей подключаются к системе телепортации для обработки перемещения пользователя в расположение, на который указывает указатель.

Посредник указателя

Так как у одного контроллера может быть несколько указателей (например, у шарнирной руки могут быть как ближайшие, так и дальние указатели взаимодействия), существует компонент, отвечающий за медиатирование того, какой указатель должен быть активен.

Например, когда рука пользователя приближается к нажатой кнопке, ShellHandRayPointer объект должен перестать отображаться, а PokePointer должен быть задействован.

Это обрабатывается DefaultPointerMediator, который отвечает за определение активных указателей на основе состояния всех указателей. Одним из ключевых моментов этого действия является отключение дальних указателей, когда близкий указатель находится рядом с объектом (см. раздел DefaultPointerMediator).

Можно предоставить альтернативную реализацию медиатора указателя, изменив PointerMediator свойство в профиле указателя.

Отключение указателей

Поскольку медиатор указателя запускает каждый кадр, он в конечном итоге управляет активным или неактивным состоянием всех указателей. Таким образом, если задать свойство IsInteractionEnabled указателя в коде, он будет перезаписан медиатором указателя каждый кадр. Вместо этого можно указать PointerBehavior , чтобы управлять включением или выключением указателей. Обратите внимание, что это будет работать, только если вы используете значения по умолчанию FocusProvider и DefaultPointerMediator в MRTK.

Пример. Отключение лучей рук в MRTK

Следующий код отключает лучи рук в MRTK:

// Turn off all hand rays
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff);

// Turn off hand rays for the right hand only
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Right);

Следующий код возвращает лучи рук к их поведению по умолчанию в MRTK:

PointerUtils.SetHandRayPointerBehavior(PointerBehavior.Default);

Следующий код будет принудительно включить лучи рук, независимо от того, находится ли рядом с захватом:

// Turn off all hand rays
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOn);

Дополнительные примеры см PointerUtils . в разделе и TurnPointersOnOff .

FocusProvider

FocusProvider это рабочая лошадка, которая отвечает за перебор списка всех указателей и определение фокуса объекта для каждого указателя.

В каждом Update() вызове это будет:

  1. Обновите все указатели путем вещания лучей и обнаружения попаданий в соответствии с настройками самого указателя (например, указатель сферы может указать SphereOverlap raycastMode, поэтому FocusProvider выполнит столкновение на основе сферы).

  2. Обновите объект с фокусом для каждого указателя (т. е. если объект получил фокус, он также активирует события для этого объекта, если объект потерял фокус, он приведет к потере фокуса и т. д.).

Конфигурация и жизненный цикл указателя

Указатели можно настроить в разделе Указатели системного профиля ввода.

Время существования указателя обычно имеет следующий тип:

  1. Диспетчер устройств обнаружит наличие контроллера. Затем этот диспетчер устройств создаст набор указателей, связанных с контроллером, посредством вызова RequestPointersметода .

  2. FocusProvider в цикле Update() выполнит итерацию по всем допустимым указателям и выполнит связанную логику обнаружения лучей или попаданий. Используется для определения объекта, который сосредоточен по каждому конкретному указателю.

    • Так как можно одновременно иметь несколько источников ввода (например, две активные руки), можно также иметь несколько объектов, имеющих фокус одновременно.
  3. Диспетчер устройств, обнаружив, что источник контроллера был потерян, будет удалять указатели, связанные с потерянным контроллером.