Контроллеры движения в Unity

В HoloLens и иммерсивном HMD есть два основных способа выполнения действий в Unity, жестов рук и контроллеров движения . Доступ к данным для обоих источников пространственного ввода можно получить через одни и те же API в Unity.

Unity предоставляет два основных способа доступа к пространственным входным данным для Windows Mixed Reality. Общие API Input.GetButton/Input.GetAxis работают в нескольких пакетах SDK XR Unity, а API InteractionManager/GestureRecognizer, характерный для Windows Mixed Reality, предоставляет полный набор пространственных входных данных.

API входных данных Unity XR

Для новых проектов рекомендуется использовать новые API-интерфейсы ввода XR с самого начала.

Дополнительные сведения об API XR можно найти здесь.

Таблица сопоставления кнопок и осей Unity

Диспетчер ввода Unity для Windows Mixed Reality контроллеров движения поддерживает идентификаторы кнопок и осей, перечисленные ниже с помощью API Input.GetButton/GetAxis. Столбец Windows MR ссылается на свойства, доступные по типу InteractionSourceState . Каждый из этих API подробно описан в разделах ниже.

Сопоставления идентификаторов кнопки и оси для Windows Mixed Reality обычно соответствуют идентификаторам кнопки или оси Oculus.

Сопоставления идентификаторов кнопки и оси для Windows Mixed Reality отличаются от сопоставлений OpenVR двумя способами:

  1. В сопоставлении используются идентификаторы сенсорной панели, отличные от палец, для поддержки контроллеров с обоими пальцами и сенсорной панелью.
  2. Сопоставление позволяет избежать перегрузки идентификаторов кнопок A и X для кнопок меню, чтобы оставить их доступными для физических кнопок ABXY.
Входные данныеРаспространенные API Unity
(Input.GetButton/GetAxis)
API ввода, зависящего от Windows MR
(XR. WSA. Входные данные)
Левая рука Десница
Нажатие триггера Ось 9 = 1,0 Ось 10 = 1,0 selectPressed
Выбор аналогового значения триггера Ось 9 Ось 10 selectPressedAmount
Выбор триггера с частичным нажатием Кнопка 14 (геймпад compat) Кнопка 15 (геймпад compat) selectPressedAmount > 0.0
Нажатие кнопки меню Кнопка 6* Кнопка 7* menuPressed
Нажатие кнопки захвата Ось 11 = 1,0 (без аналоговых значений)
Кнопка 4 (геймпад compat)
Ось 12 = 1,0 (без аналоговых значений)
Кнопка 5 (геймпад compat)
схваченный
Thumbstick X (слева: -1.0, справа: 1.0) Ось 1 Ось 4 thumbstickPosition.x
Thumbstick Y (сверху: -1.0, внизу: 1.0) Ось 2 Ось 5 thumbstickPosition.y
Отжатый палец Кнопка 8 Кнопка 9 thumbstickPressed
Touchpad X (слева: -1.0, справа: 1.0) Ось 17* Ось 19* touchpadPosition.x
Сенсорная панель Y (сверху: -1.0, внизу: 1.0) Ось 18* Ось 20* touchpadPosition.y
Касание сенсорной панели Кнопка 18* Кнопка 19* touchpadTouched
Нажатие сенсорной панели Кнопка 16* Кнопка 17* touchpadPressed
Положение захвата 6DoF или положение указателя Только захват поз: XR. InputTracking.GetLocalPosition
XR. InputTracking.GetLocalRotation
Передача захвата или указателя в качестве аргумента: sourceState.sourcePose.TryGetPosition
sourceState.sourcePose.TryGetRotation
Отслеживание состояния Точность положения и риск потери источника, доступные только через API mr-specific sourceState.sourcePose.positionAccuracy
sourceState.properties.sourceLossRisk

Примечание

Эти идентификаторы кнопок и осей отличаются от идентификаторов, используемых Unity для OpenVR из-за конфликтов в сопоставлениях, используемых геймпадами, Oculus Touch и OpenVR.

OpenXR

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

Подключаемый модуль OpenXR Смешанная реальность предоставляет дополнительные профили взаимодействия ввода, сопоставленные со стандартными значениями InputFeatureUsage, как описано ниже:

InputFeatureUsage Hp Reverb G2 Controller (OpenXR) HoloLens Hand (OpenXR)
primary2DAxis Джойстик
primary2DAxisClick Джойстик — щелкните
триггер Триггер
хватка Хватка Касание воздуха или сжатие
primaryButton [X/A] — нажмите Жест касания
secondaryButton [Y/B] — нажмите
gripButton Захват — нажатие
triggerButton Триггер — нажатие
menuButton Меню

Положение захвата и положение указателя

Windows Mixed Reality поддерживает контроллеры движения в различных форм-факторах. Дизайн каждого контроллера отличается своей связью между положением руки пользователя и естественным направлением "вперед", которое приложения должны использовать для указания при отрисовке контроллера.

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

Положение захвата

Поза захвата представляет расположение ладони пользователей, обнаруженную HoloLens или удерживая контроллер движения.

На иммерсивных гарнитурах положение захвата лучше всего использовать для отрисовки руки пользователя или объекта, удерживаемого в руке пользователя. Положение захвата также используется при визуализации контроллера движения. Модель , предоставляемая Windows для контроллера движения, использует положение захвата в качестве источника и центра поворота.

Положение захвата определяется специально следующим образом:

  • Положение захвата: центроид ладони при естественном удержании контроллера корректируется влево или вправо, чтобы центрировать положение внутри захвата. На Windows Mixed Reality контроллере движения эта позиция обычно выравнивается с кнопкой захвата.
  • Правая ось захвата: Когда вы полностью открываете руку, чтобы сформировать плоскую 5-палец позу, луч, который является нормальным для вашей ладони (вперед с левой ладони, назад от правой ладони)
  • Ось направления захвата: когда вы частично закроете руку (как будто удерживая контроллер), луч, указывающий "вперед" через трубку, сформированную пальцами без пальца.
  • Ось вверх ориентации захвата: ось вверх, подразумеваемая определениями "Правая" и "Вперед".

Доступ к позе захвата можно получить с помощью API ввода между поставщиками (XR) Unity. InputTracking. GetLocalPosition/Rotation) или через API windows MR (sourceState.sourcePose.TryGetPosition/Rotation, запрашивая данные представления для узла Grip ).

Положение указателя

Положение указателя представляет кончик контроллера, указывающего вперед.

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

В настоящее время положение указателя доступно в Unity только через API windows MR, sourceState.sourcePose.TryGetPosition/Rotation, передавая InteractionSourceNode.Pointer в качестве аргумента.

OpenXR

У вас есть доступ к двум наборам поз с помощью взаимодействий ввода OpenXR:

  • Захват позирует для отрисовки объектов в руке
  • Цель представляет для указания на мир.

Дополнительные сведения об этой структуре и различиях между двумя позами можно найти в спецификации OpenXR — входных подпатках.

Представления, предоставляемые InputFeatureUsages DevicePosition, DeviceRotation, DeviceVelocity и DeviceAngularVelocity, представляют собой позу захвата OpenXR. InputFeatureUsages, связанные с позами захвата, определяются в CommonUsages Unity.

Представления, предоставляемые InputFeatureUsages PointerPosition, PointerRotation, PointerVelocity и PointerAngularVelocity, представляют позу цели OpenXR. Эти inputFeatureUsages не определены в включенных файлах C#, поэтому вам потребуется определить собственные inputFeatureUsages следующим образом:

public static readonly InputFeatureUsage<Vector3> PointerPosition = new InputFeatureUsage<Vector3>("PointerPosition");

Тактильные хаптики

Сведения об использовании тактильной системы ввода XR в Unity см. в руководстве по Unity xR Input — Haptics.

Состояние отслеживания контроллера

Как и гарнитуры, контроллер движения Windows Mixed Reality не требует установки внешних датчиков отслеживания. Вместо этого контроллеры отслеживаются датчиками в самой гарнитуре.

Если пользователь перемещает контроллеры из поля зрения гарнитуры, Windows продолжает выводить позиции контроллера в большинстве случаев. Когда контроллер потерял визуальное отслеживание достаточно долго, позиции контроллера будут удалены до приблизительной точности позиций.

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

Явное обоснование состояния отслеживания

Приложения, которые хотят обрабатывать позиции по-разному в зависимости от состояния отслеживания, могут идти дальше и проверять свойства состояния контроллера, такие как SourceLossRisk и PositionAccuracy:

Отслеживание состояния SourceLossRisk PositionAccuracacy TryGetPosition
Высокая точность < 1.0 Высокий Да
Высокая точность (в опасности потери) == 1.0 Высокий Да
Приблизительная точность == 1.0 Приблизительна Да
Нет позиции == 1.0 Приблизительна false

Эти состояния отслеживания контроллера движения определяются следующим образом:

  • Высокая точность: Хотя контроллер движения находится в поле зрения гарнитуры, он обычно предоставляет позиции высокой точности на основе визуального отслеживания. Движущийся контроллер, который временно покидает поле зрения или на мгновение скрывается от датчиков гарнитуры (например, с другой стороны пользователя) будет продолжать возвращать высокоточные представления в течение короткого времени на основе инерционного отслеживания самого контроллера.
  • Высокая точность (в опасности потери): Когда пользователь перемещает контроллер движения мимо края поля зрения гарнитуры, гарнитура скоро не сможет визуально отслеживать положение контроллера. Приложение знает, когда контроллер достиг этой границы FOV, увидев , что SourceLossRisk достигает 1,0. На этом этапе приложение может приостановить жесты контроллера, для которых требуется устойчивый поток высококачественных поз.
  • Приблизительная точность: Когда контроллер потерял визуальное отслеживание достаточно долго, позиции контроллера будут удалены до приблизительной точности позиций. На этом этапе система заблокирует контроллер пользователю, отслеживая позицию пользователя по мере перемещения, сохраняя при этом истинную ориентацию контроллера с помощью своих внутренних датчиков ориентации. Многие приложения, использующие контроллеры для указания и активации элементов пользовательского интерфейса, могут работать в обычном режиме, не замечая пользователя. Приложения с более высокими требованиями к входным данным могут понять это падение с высокой точности до приблизительной точности, проверив свойство PositionAccuracy , например, чтобы предоставить пользователю более щедрый целевой элемент hitbox на внеэкранных целевых объектах в течение этого времени.
  • Нет позиции: Хотя контроллер может работать с приблизительной точностью в течение длительного времени, иногда система знает, что даже положение, заблокированное телом, в данный момент не имеет смысла. Например, контроллер, который был включен, возможно, никогда не наблюдался визуально, или пользователь может поставить контроллер, который затем взял кто-то другой. В таких случаях система не предоставит приложению никакой позиции, и TryGetPosition вернет значение false.

Общие API Unity (Input.GetButton/GetAxis)

Пространство имен:UnityEngine, UnityEngine.XR
Типы: входные данные, XR. InputTracking

В настоящее время Unity использует общие API Input.GetButton/Input.GetAxis для предоставления входных данных для пакета SDK Oculus, пакета SDK OpenVR и Windows Mixed Reality, включая руки и контроллеры движения. Если приложение использует эти API для ввода, оно может легко поддерживать контроллеры движения в нескольких пакетах SDK XR, включая Windows Mixed Reality.

Получение состояния нажатия логической кнопки

Чтобы использовать общие ИНТЕРФЕЙСы API ввода Unity, вы обычно начинаете с переключения кнопок и осей для логических имен в диспетчере ввода Unity, привязки идентификаторов кнопок или осей к каждому имени. Затем можно написать код, который ссылается на это логическое имя кнопки или оси.

Например, чтобы сопоставить кнопку триггера левого контроллера движения с действием "Отправить", перейдите к разделу "Изменить > параметры проекта > " в Unity и разверните свойства раздела "Отправить" в разделе Axes. Измените свойство "Положительная кнопка " или "Alt Positive Button" , чтобы прочитать джойстик кнопку 14, как показано ниже.

InputManager Unity
Unity InputManager

Затем скрипт может проверить действие отправки с помощью Input.GetButton:

if (Input.GetButton("Submit"))
{
  // ...
}

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

Получение состояния нажатия физической кнопки напрямую

Вы также можете получить доступ к кнопкам вручную по полному имени с помощью Input.GetKey:

if (Input.GetKey("joystick button 8"))
{
  // ...
}

Получение положения руки или контроллера движения

Вы можете получить доступ к положению и повороту контроллера с помощью XR. InputTracking:

Vector3 leftPosition = InputTracking.GetLocalPosition(XRNode.LeftHand);
Quaternion leftRotation = InputTracking.GetLocalRotation(XRNode.LeftHand);

Примечание

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

Связь между этой позой захвата и положением указателя (где указатель контроллера) может отличаться между контроллерами. На данный момент доступ к позе указателя контроллера возможен только с помощью API ввода MR, описанного в разделах ниже.

API, относящиеся к Windows (XR). WSA. Входные данные)

Внимание!

Если проект использует любой из XR. API WSA постепенно удаляются в пользу пакета SDK XR в будущих выпусках Unity. Для новых проектов рекомендуется использовать пакет SDK XR с самого начала. Дополнительные сведения о системе ввода XR и API см. здесь.

Пространство имен:UnityEngine.XR.WSA.Input
Типы: InteractionManager, InteractionSourceState, InteractionSource, InteractionSourceProperties, InteractionSourceKind, InteractionSourceLocation

Чтобы получить более подробные сведения о Windows Mixed Reality ручном вводе (для HoloLens) и контроллерах движения, можно использовать API пространственных входных данных Windows в пространстве имен UnityEngine.XR.WSA.Input. Это позволяет получить доступ к дополнительным сведениям, таким как точность положения или тип источника, что позволяет сообщать рукам и контроллерам друг от друга.

Опрос состояния рук и контроллеров движения

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

var interactionSourceStates = InteractionManager.GetCurrentReading();
foreach (var interactionSourceState in interactionSourceStates) {
    // ...
}

Каждый объект InteractionSourceState , который вы возвращаете, представляет источник взаимодействия в текущий момент времени. InteractionSourceState предоставляет такие сведения, как:

  • Какие типы нажатий происходят (выбор,меню/захват/сенсорной панели/thumbstick)

    if (interactionSourceState.selectPressed) {
         // ...
    }
    
  • Другие данные, относящиеся к контроллерам движения, такие как координаты сенсорной панели и /или палец XY и состояние касания

    if (interactionSourceState.touchpadTouched && interactionSourceState.touchpadPosition.x > 0.5) {
         // ...
    }
    
  • InteractionSourceKind, чтобы узнать, является ли источник рукой или контроллером движения.

    if (interactionSourceState.source.kind == InteractionSourceKind.Hand) {
         // ...
    }
    

Опрос для прогнозируемых предпрогнозируемых поз отрисовки

  • При опросе исходных данных взаимодействия от рук и контроллеров позы, которые вы получаете вперед прогнозируемые позы на данный момент времени, когда фотоны этого кадра будут достигать глаз пользователя. Прогнозируемые позы лучше всего используются для отрисовки контроллера или удерживаемого объекта каждого кадра. Если вы нацелены на заданный пресс-релиз с контроллером, это будет наиболее точным, если вы используете API исторических событий, описанные ниже.

    var sourcePose = interactionSourceState.sourcePose;
    Vector3 sourceGripPosition;
    Quaternion sourceGripRotation;
    if ((sourcePose.TryGetPosition(out sourceGripPosition, InteractionSourceNode.Grip)) &&
         (sourcePose.TryGetRotation(out sourceGripRotation, InteractionSourceNode.Grip))) {
         // ...
    }
    
  • Вы также можете получить прогнозируемый вперед головной позы для этого текущего кадра. Как и в исходной позе, это полезно для отрисовки курсора, хотя назначение заданного прессы или выпуска будет наиболее точным, если вы используете API исторических событий, описанные ниже.

    var headPose = interactionSourceState.headPose;
    var headRay = new Ray(headPose.position, headPose.forward);
    RaycastHit raycastHit;
    if (Physics.Raycast(headPose.position, headPose.forward, out raycastHit, 10)) {
         var cursorPos = raycastHit.point;
         // ...
    }
    

Обработка событий источника взаимодействия

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

Для обработки событий источника взаимодействия:

  • Зарегистрируйтесь для входного события InteractionManager . Для каждого интересующего вас события взаимодействия необходимо подписаться на него.

    InteractionManager.InteractionSourcePressed += InteractionManager_InteractionSourcePressed;
    
  • Обработка события. После подписки на событие взаимодействия вы получите обратный вызов при необходимости. В примере SourcePressed это будет после обнаружения источника и до его освобождения или потери.

    void InteractionManager_InteractionSourceDetected(InteractionSourceDetectedEventArgs args)
         var interactionSourceState = args.state;
    
         // args.state has information about:
            // targeting head ray at the time when the event was triggered
            // whether the source is pressed or not
            // properties like position, velocity, source loss risk
            // source id (which hand id for example) and source kind like hand, voice, controller or other
    }
    

Как остановить обработку события

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

InteractionManager.InteractionSourcePressed -= InteractionManager_InteractionSourcePressed;

Список событий источника взаимодействия

Доступные события источника взаимодействия:

  • InteractionSourceDetected (источник становится активным)
  • InteractionSourceLost (становится неактивным)
  • InteractionSourcePressed (касание, нажатие кнопки или фраза "Выбрать")
  • InteractionSourceReleased (окончание касания, нажатия кнопки или окончания фразы Select)
  • InteractionSourceUpdated (перемещается или изменяет некоторое состояние)

События для исторической целевой настройки представляют, которые наиболее точно соответствуют прессе или выпуску

API опроса, описанные ранее, дают прогнозируемым приложениям позы. Хотя прогнозируемые позы лучше всего подходит для отрисовки контроллера или виртуального портативного объекта, будущие представления не являются оптимальными для целевого объекта, по двум ключевым причинам:

  • Когда пользователь нажимает кнопку на контроллере, может быть около 20 мс беспроводной задержки через Bluetooth, прежде чем система получит нажатие.
  • Затем, если вы используете прогнозируемую позу вперед, будет еще 10–20 мс прогноза вперед, примененного к целевому времени, когда фотоны текущего кадра достигнет глаз пользователя.

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

Чтобы точно ориентироваться на основе исходного намерения пользователя для нажатия руки или контроллера, следует использовать историческую позу источника или позу головы из этого события ввода InteractionSourcePressed или InteractionSourceReleased .

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

  • Голова позирует в момент времени, когда произошло нажатие жеста или контроллера, которое можно использовать для определения того , что пользователь смотрел на:

    void InteractionManager_InteractionSourcePressed(InteractionSourcePressedEventArgs args) {
         var interactionSourceState = args.state;
         var headPose = interactionSourceState.headPose;
         RaycastHit raycastHit;
         if (Physics.Raycast(headPose.position, headPose.forward, out raycastHit, 10)) {
             var targetObject = raycastHit.collider.gameObject;
             // ...
         }
    }
    
  • Источник позирует на данный момент, когда произошло нажатие контроллера движения, которое можно использовать для определения того, на что пользователь указывал на контроллер. Это будет состояние контроллера, который испытал нажатие. Если вы отрисовываете сам контроллер, вы можете запросить положение указателя, а не положение захвата, чтобы стрелять на целевой луч из того, что пользователь будет считать естественным кончиком этого отрисованного контроллера:

    void InteractionManager_InteractionSourcePressed(InteractionSourcePressedEventArgs args)
    {
         var interactionSourceState = args.state;
         var sourcePose = interactionSourceState.sourcePose;
         Vector3 sourceGripPosition;
         Quaternion sourceGripRotation;
         if ((sourcePose.TryGetPosition(out sourceGripPosition, InteractionSourceNode.Pointer)) &&
             (sourcePose.TryGetRotation(out sourceGripRotation, InteractionSourceNode.Pointer))) {
             RaycastHit raycastHit;
             if (Physics.Raycast(sourceGripPosition, sourceGripRotation * Vector3.forward, out raycastHit, 10)) {
                 var targetObject = raycastHit.collider.gameObject;
                 // ...
             }
         }
    }
    

Пример обработчиков событий

using UnityEngine.XR.WSA.Input;

void Start()
{
    InteractionManager.InteractionSourceDetected += InteractionManager_InteractionSourceDetected;
    InteractionManager.InteractionSourceLost += InteractionManager_InteractionSourceLost;
    InteractionManager.InteractionSourcePressed += InteractionManager_InteractionSourcePressed;
    InteractionManager.InteractionSourceReleased += InteractionManager_InteractionSourceReleased;
    InteractionManager.InteractionSourceUpdated += InteractionManager_InteractionSourceUpdated;
}

void OnDestroy()
{
    InteractionManager.InteractionSourceDetected -= InteractionManager_InteractionSourceDetected;
    InteractionManager.InteractionSourceLost -= InteractionManager_InteractionSourceLost;
    InteractionManager.InteractionSourcePressed -= InteractionManager_InteractionSourcePressed;
    InteractionManager.InteractionSourceReleased -= InteractionManager_InteractionSourceReleased;
    InteractionManager.InteractionSourceUpdated -= InteractionManager_InteractionSourceUpdated;
}

void InteractionManager_InteractionSourceDetected(InteractionSourceDetectedEventArgs args)
{
    // Source was detected
    // args.state has the current state of the source including id, position, kind, etc.
}

void InteractionManager_InteractionSourceLost(InteractionSourceLostEventArgs state)
{
    // Source was lost. This will be after a SourceDetected event and no other events for this
    // source id will occur until it is Detected again
    // args.state has the current state of the source including id, position, kind, etc.
}

void InteractionManager_InteractionSourcePressed(InteractionSourcePressedEventArgs state)
{
    // Source was pressed. This will be after the source was detected and before it is
    // released or lost
    // args.state has the current state of the source including id, position, kind, etc.
}

void InteractionManager_InteractionSourceReleased(InteractionSourceReleasedEventArgs state)
{
    // Source was released. The source would have been detected and pressed before this point.
    // This event will not fire if the source is lost
    // args.state has the current state of the source including id, position, kind, etc.
}

void InteractionManager_InteractionSourceUpdated(InteractionSourceUpdatedEventArgs state)
{
    // Source was updated. The source would have been detected before this point
    // args.state has the current state of the source including id, position, kind, etc.
}

Контроллеры движения в MRTK

Доступ к жесту и контроллеру движения можно получить из диспетчера входных данных.

Обучение по руководствам

Пошаговые руководства с более подробными примерами настройки доступны в Смешанная реальность Академии:

Mr Input 213 — контроллер движения
Mr Input 213 — контроллер движения

Следующий этап разработки

Если вы следите за процессом разработки Unity, который мы изложили, вы находитесь в разгар изучения основных стандартных блоков MRTK. Отсюда вы можете перейти к следующему стандартному блоку:

Или перейдите к возможностям и API платформы смешанной реальности:

Вы можете в любой момент вернуться к этапам разработки для Unity.

См. также статью