Добавление близкого взаимодействия — MRTK2

Близкие взаимодействия приходят в виде касаний и захватов. События касания и захвата вызываются как события указателя pokePointer и SpherePointer соответственно.

Для прослушивания событий сенсорного ввода и (или) захвата в определенном GameObject требуется три ключевых шага.

  1. Убедитесь, что соответствующий указатель зарегистрирован в профиле конфигурации MAIN MRTK.
  2. Убедитесь, что нужный GameObject имеет соответствующий компонент сценария захвата или сенсорного ввода и Unity Collider.
  3. Реализуйте интерфейс обработчика входных данных в присоединенном скрипте к нужному объекту GameObject для прослушивания событий захвата или сенсорного ввода .

Добавление взаимодействий захвата

  1. Убедитесь, что SpherePointer зарегистрирован в профиле указателя MRTK.

    Профиль MRTK по умолчанию и профиль HoloLens 2 по умолчанию уже содержат SpherePointer. Чтобы убедиться, что SpherePointer будет создан, выберите профиль конфигурации MRTK и перейдите в разделПараметры указателявходных>указателей>. Заготовка по умолчанию GrabPointer (Assets/MRTK/SDK/Features/UX/Prefabs/Pointers) должна быть указана с типом контроллераШарообразная рука. Пользовательская заготовка SpherePointer может использоваться до тех пор, пока она реализует класс .

    Пример профиля указателя захвата

    По умолчанию указатель захвата запрашивает близлежащие объекты в конусе вокруг точки захвата в соответствии с интерфейсом HoloLens 2 по умолчанию.

    Конический указатель захвата

  2. В GameObject, который должен быть захватываемым, добавьте NearInteractionGrabbable, а также коллайдер.

    Убедитесь, что слой GameObject находится на захватываемом слое. По умолчанию захватываются все слои, кроме пространственной осведомленности и пропускания лучей . Чтобы узнать, какие слои можно захватывать, проверьте маски слоя захвата в заготовкеGrabPointer .

  3. В GameObject или одном из его предков добавьте компонент скрипта, реализующий IMixedRealityPointerHandler интерфейс . Любой предок объекта с параметром NearInteractionGrabbable также сможет получать события указателя.

Пример кода захвата

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

public class PrintPointerEvents : MonoBehaviour, IMixedRealityPointerHandler
{
    public void OnPointerDown(MixedRealityPointerEventData eventData)
    {
        if (eventData.Pointer is SpherePointer)
        {
            Debug.Log($"Grab start from {eventData.Pointer.PointerName}");
        }
        if (eventData.Pointer is PokePointer)
        {
            Debug.Log($"Touch start from {eventData.Pointer.PointerName}");
        }
    }

    public void OnPointerClicked(MixedRealityPointerEventData eventData) {}
    public void OnPointerDragged(MixedRealityPointerEventData eventData) {}
    public void OnPointerUp(MixedRealityPointerEventData eventData) {}
}

Добавление сенсорных взаимодействий

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

Однако для обоих типов элементов пользовательского интерфейса убедитесь, что PokePointer зарегистрирован в профиле указателя MRTK.

Профиль MRTK по умолчанию и профиль HoloLens 2 по умолчанию уже содержат PokePointer. Чтобы убедиться, что PokePointer будет создан, выберите профиль конфигурации MRTK и перейдите в разделПараметры указателявходных>указателей>. Заготовка по умолчанию PokePointer (Assets/MRTK/SDK/Features/UX/Prefabs/Pointers) должна быть указана с типом контроллерас шарнирной рукой. Пользовательская заготовка PokePointer может использоваться до тех пор, пока она реализует класс .

Пример профиля указателя poke

3D GameObjects

Существует два разных способа добавления сенсорных взаимодействий в трехмерные объекты GameObject, в зависимости от того, должен ли ваш трехмерный объект иметь только одну плоскость, доступную для касания, или от того, должен ли он быть осязаемым на основе всего коллайдера. Первый способ обычно используется для объектов с BoxColliders, где требуется, чтобы только одна грань коллайдера реагировала на события касания. Другая — для объектов, которые должны быть доступны для касания с любого направления в зависимости от их коллайдера.

Касание с одним лицом

Это полезно для ситуаций, когда только одно лицо должно быть осязаемым. Этот параметр предполагает, что игровой объект имеет BoxCollider. это можно использовать с объектами, не связанными с BoxCollider. В этом случае свойства "Границы" и "Локальный центр" часто задаются вручную для настройки плоскости, допускающей касание (т. е. для границ следует задать ненулевое значение).

  1. В GameObject, который должен быть сенсорным, добавьте BoxCollider и NearInteractionTouchable компонент.

    1. Если используется интерфейс в приведенном ниже скрипте IMixedRealityTouchHandler компонента, установите для параметра Events (Получить) значение Touch (Получить) на касание.

    2. Щелкните "Исправить границы" и "Центр исправления".

    Настройка NearInteractionTouchable

  2. Для этого объекта или одного из его предков добавьте компонент скрипта, реализующийинтерфейса IMixedRealityTouchHandler. Любой предок объекта с параметром NearInteractionTouchable также сможет получать события указателя.

Примечание

В представлении сцены редактора с выбранным объектом NearInteractionTouchable GameObject обратите внимание на белый квадрат контура и стрелку. Стрелка указывает на "переднюю" часть сенсорного объекта. Контакт с возможностью взаимодействия будет доступен только в этом направлении. Сведения о том, как сделать коллайдер пригодным для касания со всех сторон, см. в разделе о произвольном касании коллайдера. NearInteractionTouchable Gizmos

Произвольное касание коллайдера

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

  1. В GameObject, который должен быть сенсорным, добавьте коллайдер и NearInteractionTouchableVolume компонент.

    1. Если используется интерфейс в приведенном ниже скрипте IMixedRealityTouchHandler компонента, установите для параметра Events (Получить) значение Touch (Получить) на касание.
  2. Для этого объекта или одного из его предков добавьте компонент скрипта, реализующийинтерфейса IMixedRealityTouchHandler. Любой предок объекта с параметром NearInteractionTouchable также сможет получать события указателя.

Пользовательский интерфейс Unity

  1. Добавьте или убедитесь, что в сцене есть холст UnityUI .

  2. Добавьте NearInteractionTouchableUnityUI компонент в GameObject, который должен быть касаемым.

    1. Если используется интерфейс в приведенном ниже скрипте IMixedRealityTouchHandler компонента, установите для параметра Events (Получить) значение Touch (Получить) на касание.
  3. Для этого объекта или одного из его предков добавьте компонент скрипта, реализующий IMixedRealityTouchHandler интерфейс . Любой предок объекта с параметром NearInteractionTouchableUnityUI также сможет получать события указателя.

Важно!

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

Важно!

В компоненте скрипта NearInteractionTouchable для свойства События для получения есть два варианта: Указатель и Сенсорный. Задайте для параметра События значение Получить значение Указатель , если используется IMixedRealityPointerHandler интерфейс, и для параметра Touch при использовании IMixedRealityTouchHandler интерфейса в скрипте компонента, который отвечает или обрабатывает входные события.

Пример сенсорного кода

В приведенном ниже коде демонстрируется monoBehaviour, который можно присоединить к GameObject с NearInteractionTouchable помощью компонента variant и реагировать на события сенсорного ввода.

public class TouchEventsExample : MonoBehaviour, IMixedRealityTouchHandler
{
    public void OnTouchStarted(HandTrackingInputEventData eventData)
    {
        string ptrName = eventData.Pointer.PointerName;
        Debug.Log($"Touch started from {ptrName}");
    }
    public void OnTouchCompleted(HandTrackingInputEventData eventData) {}
    public void OnTouchUpdated(HandTrackingInputEventData eventData) { }
}

Примеры сценариев близкого взаимодействия

События касания

Этот пример создает куб, делает его сенсорным и изменяет цвет при касании.

public static void MakeChangeColorOnTouch(GameObject target)
{
    // Add and configure the touchable
    var touchable = target.AddComponent<NearInteractionTouchableVolume>();
    touchable.EventsToReceive = TouchableEventType.Pointer;

    var material = target.GetComponent<Renderer>().material;
    // Change color on pointer down and up
    var pointerHandler = target.AddComponent<PointerHandler>();
    pointerHandler.OnPointerDown.AddListener((e) => material.color = Color.green);
    pointerHandler.OnPointerUp.AddListener((e) => material.color = Color.magenta);
}

События захвата

В приведенном ниже примере показано, как сделать GameObject перетаскиваемым. Предполагается, что игровой объект имеет коллайдер.

public static void MakeNearDraggable(GameObject target)
{
    // Instantiate and add grabbable
    target.AddComponent<NearInteractionGrabbable>();

    // Add ability to drag by re-parenting to pointer object on pointer down
    var pointerHandler = target.AddComponent<PointerHandler>();
    pointerHandler.OnPointerDown.AddListener((e) =>
    {
        if (e.Pointer is SpherePointer)
        {
            target.transform.parent = ((SpherePointer)(e.Pointer)).transform;
        }
    });
    pointerHandler.OnPointerUp.AddListener((e) =>
    {
        if (e.Pointer is SpherePointer)
        {
            target.transform.parent = null;
        }
    });
}

Полезные интерфейсы API

См. также раздел