250. Общий доступ в смешанной реальности: HoloLens и иммерсивные гарнитурыMR Sharing 250: HoloLens and immersive headsets

Примечание

Руководства Mixed Reality Academy были разработаны для иммерсивных гарнитур HoloLens (1-го поколения) и иммерсивных гарнитур Mixed Reality.The Mixed Reality Academy tutorials were designed with HoloLens (1st gen) and Mixed Reality Immersive Headsets in mind. Поэтому мы считаем, что важно оставить эти руководства для разработчиков, которые ищут рекомендации по разработке для этих устройств.As such, we feel it is important to leave these tutorials in place for developers who are still looking for guidance in developing for those devices. Данные руководства не будут обновляться с учетом последних наборов инструментов или возможностей взаимодействия для HoloLens 2.These tutorials will not be updated with the latest toolsets or interactions being used for HoloLens 2. Они будут сохранены для работы на поддерживаемых устройствах.They will be maintained to continue working on the supported devices. Опубликован новый цикл руководств для HoloLens 2.A new series of tutorials has been posted for HoloLens 2.

Благодаря гибкости универсальная платформа Windows (UWP) легко создать приложение, охватывающее несколько устройств.With the flexibility of Universal Windows Platform (UWP), it is easy to create an application that spans multiple devices. Благодаря этой гибкости мы можем создавать возможности, использующие сильные стороны каждого устройства.With this flexibility, we can create experiences that leverage the strengths of each device. В этом учебнике рассматривается базовый общий интерфейс, который работает на впечатляющих головных и HoloLens и Windows Mixed Reality.This tutorial will cover a basic shared experience that runs on both HoloLens and Windows Mixed Reality immersive headsets. Это содержимое изначально было доставлено на конференцию Microsoft Build 2017 в Сиэтле, штат Вашингтон.This content was originally delivered at the Microsoft Build 2017 conference in Seattle, WA.

В этом учебнике мы выполним следующее:In this tutorial, we will:

  • Настройка сети с помощью УНЕТ.Setup a network using UNET.
  • Делитесь голограммами на устройствах смешанной реальности.Share holograms across mixed reality devices.
  • Установите другое представление приложения в зависимости от того, какое устройство смешанной реальности используется.Establish a different view of the application depending on which mixed reality device is being used.
  • Создавайте общие возможности, когда пользователи HoloLens изменяют впечатляющие гарнитуры с помощью простых головоломок.Create a shared experience where HoloLens users guide immersive headsets users through some simple puzzles.

Поддержка устройствDevice support

КурсCourse HoloLensHoloLens Иммерсивные гарнитурыImmersive headsets
250. Общий доступ в смешанной реальности: HoloLens и иммерсивные гарнитурыMR Sharing 250: HoloLens and immersive headsets ✔️✔️ ✔️✔️

Прежде чем начатьBefore you start

Предварительные условияPrerequisites

Файлы проектаProject files

Примечание

Если вы хотите просмотреть исходный код перед загрузкой, он доступен на сайте GitHub.If you want to look through the source code before downloading, it's available on GitHub.

Глава 1 — Холо WorldChapter 1 - Holo World

ЗадачиObjectives

Убедитесь, что среда разработки готова к работе с простым проектом.Make sure the development environment is ready to go with a simple project.

Что будет построеноWhat we will build

Приложение, которое показывает голограмму на HoloLens или на иммерсивное гарнитуру Windows Mixed Reality.An application that shows a hologram on either HoloLens or a Windows Mixed Reality immersive headset.

ШагиSteps

  • Откройте Unity.Open Unity.
    • Выберите Open (Открыть).Select Open.
    • Перейдите к папке, в которую вы извлекли файлы проекта.Navigate to where you extracted the project files.
    • Щелкните элемент Выбор папки.Click Select Folder.
    • В то время как Unity будет в первый раз обрабатывать проект, это займет немного времени.It will take a little while for Unity to process the project the first time.
  • Убедитесь, что Смешанная реальность включена в Unity.Check that Mixed Reality is enabled in Unity.
    • Откройте диалоговое окно "параметры сборки" (Control + Shift + B или файл > параметры сборки...).Open the build settings dialog (Control+Shift+B or File > Build Settings...).
    • Выберите универсальная платформа Windows а затем выберите параметр платформа.Select Universal Windows Platform then click Switch Platform.
    • Выберите изменить>параметры проигрывателя.Select Edit>Player Settings.
    • На панели инспектора с правой стороны разверните узел Параметры XR.In the Inspector panel on the right hand side, expand XR Settings.
    • Установите флажок поддерживается виртуальная реальность .Check the Virtual Reality Supported box.
    • Windows Mixed Reality должна быть пакетом SDK виртуальной реальности.Windows Mixed Reality should be the Virtual Reality SDK.
  • Создайте сцену.Create a scene.
    • В иерархии щелкните правой кнопкой мыши Главная камера и выберите Удалить.In the Hierarchy right click Main Camera select Delete.
    • Из холотулкит > входные > Prefabs перетащите микседреалитикамерапарент в иерархию.From HoloToolkit > Input > Prefabs drag MixedRealityCameraParent to the Hierarchy.
  • Добавление голограмм в сценуAdd Holograms to the scene
    • Из апппрефабс перетащите Скибокс в представление сцены.From AppPrefabs drag Skybox to the Scene View.
    • Из апппрефабс перетащите Диспетчеры в иерархию.From AppPrefabs drag Managers to the Hierarchy.
    • Из области апппрефабс перетащите область в иерархию.From AppPrefabs drag Island to the Hierarchy.
  • Сохранить и собратьSave And build
    • Сохраните (либо Control + S , либо Файловая > сохранить сцену)Save (either Control+S or File > Save Scene)
    • Так как это новая сцена, ее необходимо присвоить имя.Since this is a new scene, you'll need to name it. Имя не имеет значения, но мы используем Шаредмикседреалити.Name doesn't matter, but we use SharedMixedReality.
  • Экспорт в Visual StudioExport To Visual Studio
    • Откройте меню Сборка (Control + Shift + B или файл > параметры сборки).Open the build menu (Control+Shift+B or File > Build Settings)
    • Нажмите кнопку Добавить открытые сцены.Click Add Open Scenes.
    • Проверка проектов C# для UnityCheck Unity C# Projects
    • Щелкните Построить.Click Build.
    • В открывшемся окне проводника создайте новую папку с именем app.In the file explorer window that appears, create a New Folder named App.
    • Щелкните папку приложения одним щелчком мыши.Single click the App folder.
    • Нажмите кнопку выбрать папку.Press Select Folder.
    • Дождитесь завершения сборкиWait for the build to complete
    • В открывшемся окне проводника перейдите в папку приложения .In the file explorer window that appears, navigate into the App folder.
    • Дважды щелкните шаредмикседреалити. sln , чтобы запустить Visual StudioDouble-click SharedMixedReality.sln to launch Visual Studio
  • Сборка из Visual StudioBuild From Visual Studio
    • Использование верхней панели инструментов изменяет целевой объект на выпуск и x86.Using the top toolbar change target to Release and x86.
    • Щелкните стрелку рядом с пунктом локальный компьютер и выберите устройство для развертывания в HoloLens.Click the arrow next to Local Machine and select Device to deploy to HoloLens
    • Щелкните стрелку рядом с полем устройство и выберите локальный компьютер для развертывания на гарнитуре Mixed Reality.Click the arrow next to Device and select Local Machine to deploy for the mixed reality headset.
    • Щелкните Отладка->начать без отладки или Control + F5 , чтобы запустить приложение.Click Debug->Start Without Debugging or Control+F5 to start the application.

Продвигаясь вглубь в кодDigging into the code

На панели проект перейдите к ассетс\холотулкит\инпут\скриптс\утилитиес и дважды щелкните MixedRealityCameraManager.CS , чтобы открыть его.In the project panel, navigate to Assets\HoloToolkit\Input\Scripts\Utilities and double click MixedRealityCameraManager.cs to open it.

Обзор: MixedRealityCameraManager.cs — это простой сценарий, который корректирует уровень качества и параметры фона на основе устройства.Overview: MixedRealityCameraManager.cs is a simple script that adjusts quality level and background settings based on the device. Здесь следует ключевое поле Холографиксеттингс. Исдисплайопакуе, которое позволяет сценарию определить, является ли устройство HoloLens (Исдисплайопакуе возвращает false) или иммерсивное гарнитура (Исдисплайопакуе возвращает true).Key here is HolographicSettings.IsDisplayOpaque, which allows a script to detect if the device is a HoloLens (IsDisplayOpaque returns false) or an immersive headset (IsDisplayOpaque returns true).

Наслаждайтесь ходом выполненияEnjoy your progress

На этом этапе приложение будет просто визуализировать голограмму.At this point the application will just render a hologram. Позже мы добавим взаимодействие к голограмме.We will add interaction to the hologram later. Оба устройства будут отображать голограмму одинаково.Both devices will render the hologram the same. На иммерсивное головной телефон также будет отображаться фон синего и облака.The immersive headset will also render a blue sky and clouds background.

Глава 2 — взаимодействиеChapter 2 - Interaction

ЗадачиObjectives

Показывает, как обрабатывать входные данные для приложения Windows Mixed Reality.Show how to handle input for a Windows Mixed Reality application.

Что будет построеноWhat we will build

Основываясь на приложении из раздела 1, мы добавим функции, позволяющие пользователю выбрать голограмму и разместить ее на реальной поверхности в HoloLens или в виртуальной таблице на современном гарнитуре.Building on the application from chapter 1, we will add functionality to allow the user to pick up the hologram and place it on a real world surface in HoloLens or on a virtual table in an immersive headset.

Обновитель ввода: В HoloLens жест выбора — это касание воздуха.Input Refresher: On HoloLens the select gesture is the air tap. На впечатляющих гарнитурах мы будем использовать кнопку на контроллере Xbox.On immersive headsets, we will use the A button on the Xbox controller. Дополнительные сведения см. в обзоре модели взаимодействия.For more information check out the interaction model overview.

ШагиSteps

  • Добавление диспетчера вводаAdd Input manager
    • Из холотулкит > входные > Prefabs перетащите InputManager в иерархию как дочерний элемент руководителей.From HoloToolkit > Input > Prefabs drag InputManager to Hierarchy as a child of Managers.
    • Из холотулкит > входные > Prefabs > курсор перетащите курсор в иерархию.From HoloToolkit > Input > Prefabs > Cursor drag Cursor to Hierarchy.
  • Добавить пространственное сопоставлениеAdd Spatial Mapping
    • Из холотулкит > спатиалмаппинг > Prefabs перетащите спатиалмаппинг в иерархию.From HoloToolkit > SpatialMapping > Prefabs drag SpatialMapping to Hierarchy.
  • Добавить виртуальный ПлайспацеAdd Virtual Playspace
    • В иерархии разверните узел микседреалитикамерапарент SELECT границаIn Hierarchy expand MixedRealityCameraParent select Boundary
    • На панели инспектора установите флажок, чтобы включить границу .In Inspector panel check the box to enable Boundary
    • Из апппрефабс перетащите вррум в иерархию.From AppPrefabs drag VRRoom to Hierarchy.
  • Добавить ВорлданчорманажерAdd WorldAnchorManager
    • В иерархии выберите Диспетчеры.In Hierarchy, Select Managers.
    • В инспекторе щелкните Добавить компонент.In Inspector, click Add Component.
    • Введите Диспетчер привязок мира.Type World Anchor Manager.
    • Выберите Диспетчер универсальных опорных точек , чтобы добавить его.Select World Anchor Manager to add it.
  • Добавление Таптоплаце к островуAdd TapToPlace to the Island
    • В иерархии разверните узел остров.In Hierarchy, expand Island.
    • Выберите микседреалитиланд.Select MixedRealityLand.
    • В инспекторе щелкните Добавить компонент.In Inspector, click Add Component.
    • Введите коснитесь, чтобы поместить и выбрать его.Type Tap To Place and select it.
    • Установите флажок " родительский элемент" для TAP.Check Place Parent On Tap.
    • Задайте для смещения размещения значение (0, 0,1, 0).Set Placement Offset to (0, 0.1, 0).
  • Сохранить и построить как преждеSave and Build as before

Продвигаясь вглубь в кодDigging into the code

Сценарий 1 — GamepadInput.csScript 1 - GamepadInput.cs

На панели проект перейдите к ассетс\холотулкит\инпут\скриптс\инпутсаурцес и дважды щелкните GamepadInput.CS , чтобы открыть его.In the project panel navigate to Assets\HoloToolkit\Input\Scripts\InputSources and double click GamepadInput.cs to open it. В том же пути на панели проекта также дважды щелкните InteractionSourceInputSource.CS.From the same path in the project panel, also double click InteractionSourceInputSource.cs.

Обратите внимание, что оба скрипта имеют общий базовый класс Басеинпутсаурце.Note that both scripts have a common base class, BaseInputSource.

Басеинпутсаурце хранит ссылку на InputManager, что позволяет сценарию запускать события.BaseInputSource keeps a reference to an InputManager, which allows a script to trigger events. В этом случае событие Инпуткликкед является существенным.In this case, the InputClicked event is relevant. Это важно помнить при получении сценария 2, Таптоплаце.This will be important to remember when we get to script 2, TapToPlace. В случае с Гамепадинпут мы будем опрашивать кнопку на контроллере, который нужно нажать, а затем вызовут событие Инпуткликкед.In the case of GamePadInput, we poll for the A button on the controller to be pressed, then we raise the InputClicked event. В случае с Интерактионсаурцеинпутсаурце мы создаем событие Инпуткликкед в ответ на Таппедевент.In the case of InteractionSourceInputSource, we raise the InputClicked event in response to the TappedEvent.

Сценарий 2 — TapToPlace.csScript 2 - TapToPlace.cs

На панели проект перейдите к ассетс\холотулкит\спатиалмаппинг\скриптс и дважды щелкните TapToPlace.CS , чтобы открыть его.In the project panel navigate to Assets\HoloToolkit\SpatialMapping\Scripts and double click TapToPlace.cs to open it.

Первое, что многие разработчики хотят реализовать при создании приложения holographic, — это перемещение голограмм с вводом жестов.The first thing many developers want to implement when creating a Holographic application is moving Holograms with gesture input. Таким образом, мы предоставили тщательное комментирование этого сценария.As such, we've endeavored to thoroughly comment this script. Для этого руководства стоит выделить несколько моментов.A few things are worth highlighting for this tutorial.

Во первых, обратите внимание, что Таптоплаце реализует Иинпуткликкхандлер.First, note that TapToPlace implements IInputClickHandler. Иинпуткликкхандлер предоставляет функции, обрабатывающие событие Инпуткликкед, вызванное GamePadInput.cs или InteractionSourceInputSource.cs.IInputClickHandler exposes the functions that handle the InputClicked event raised by GamePadInput.cs or InteractionSourceInputSource.cs. Онинпуткликкед вызывается, когда Басеинпутсаурце обнаруживает щелчок, пока объект с Таптоплаце находится в фокусе.OnInputClicked is called when a BaseInputSource detects a click while the object with TapToPlace is in focus. Аиртаппинг в HoloLens или нажатии кнопки на контроллере Xbox вызовет событие.Either airtapping on HoloLens or pressing the A button on the Xbox controller will trigger the event.

Во-вторых, код выполняется в обновлении, чтобы определить, выполняется ли поиск по поверхности, чтобы можно было поместить игровой объект на поверхность, например таблицу.Second is the code be executed in update to see if a surface is being looked at so we can place the game object on a surface, like a table. У увлекательной гарнитуры нет концепции реальных поверхностей, поэтому объект, представляющий верхнюю таблицу (Врум > Таблесинги > Кубу), был помечен с помощью Спатиалмаппинг физика, поэтому приведение лучей в Update будет конфликтовать с виртуальной таблицей сверху.The immersive headset doesn't have a concept of real surfaces, so the object that represents the table top (Vroom > TableThingy > Cube) has been marked with the SpatialMapping physics layer, so the ray cast in Update will collide with the virtual table top.

Наслаждайтесь ходом выполненияEnjoy your progress

На этот раз можно выбрать остров, чтобы переместить его.This time you can select the island to move it. В HoloLens можно переместить остров в реальную поверхность.On HoloLens you can move the island to a real surface. В поувлекательной гарнитуре можно переместить остров в виртуальную таблицу, которую мы добавили.In the immersive headset you can move the island to the virtual table we added.

Глава 3. Совместное использованиеChapter 3 - Sharing

ЗадачиObjectives

Убедитесь, что сеть настроена правильно и подробные сведения о том, как пространственные привязки являются общими для устройств.Ensure that the network is correctly configured and detail how spatial anchors are shared between devices.

Что будет построеноWhat we will build

Наш проект будет преобразован в проект с несколькими проектами.We will convert our project to a multiplayer project. Мы добавим пользовательский интерфейс и логику для размещения сеансов или подключения к ним.We will add UI and logic to host or join sessions. Пользователи HoloLens будут видеть друг друга в сеансе с облаками в своих головах, а у впечатляющих головных пользователей есть облака, расположенные рядом с точкой привязки.HoloLens users will see each other in the session with clouds over their heads, and immersive headset users have clouds near to where the anchor is. Пользователи в иммерсивное гарнитуры увидят пользователей HoloLens по отношению к источнику сцены.Users in the immersive headsets will see the HoloLens users relative to the origin of the scene. Пользователи HoloLens будут видеть голограмму острова в том же месте.HoloLens users will all see the hologram of the island in the same place. Ключевое замечание заключается в том, что пользователи в впечатляющих головных гарнитурах не будут включены в эту главу, но будут вести себя точно так же, как HoloLens, с птицм глазным представлением острова.It is key to note that the users in the immersive headsets will not be on the island during this chapter, but will behave very similarly to HoloLens, with a birds eye view of the island.

ШагиSteps

  • Удаление островка и ВррумRemove Island and VRRoom
    • В иерархии щелкните элемент остров правой кнопкой мыши, выберите пункт Удалить .In Hierarchy right-click Island select Delete
    • В иерархии щелкните правой кнопкой мыши вррум выбрать Удалить .In Hierarchy right-click VRRoom select Delete
  • Добавить УсландAdd Usland
    • Из апппрефабс перетащите усланд в иерархию.From AppPrefabs drag Usland to Hierarchy.
  • Из апппрефабс перетащите каждую из следующих элементов в иерархию:From AppPrefabs drag each of the following to Hierarchy:
    • унетшарингстажеUNETSharingStage
    • унетанчоррутUNetAnchorRoot
    • уиконтаинерUIContainer
    • дебугпанелбуттонDebugPanelButton
  • Сохранить и построить как преждеSave and Build as before

Продвигаясь вглубь в кодDigging into the code

На панели проект перейдите к ассетс\апппрефабс\суппорт\шарингвисунет\скриптс и дважды щелкните UnetAnchorManager.CS.In the project panel, navigate to Assets\AppPrefabs\Support\SharingWithUnet\Scripts and double-click on UnetAnchorManager.cs. Способность одного HoloLens обмениваться данными отслеживания с другим HoloLens, таким, что оба устройства могут совместно использовать одно и то же пространство, приближается к Magical.The ability for one HoloLens to share tracking information with another HoloLens such that both devices can share the same space is near magical. Мощь смешанной реальности вступает в активность, когда два или более пользователей могут совместно работать с одними и теми же цифровыми данными.The power of mixed reality comes alive when two or more people can collaborate using the same digital data.

Вот несколько моментов, которые необходимо указать в этом сценарии:A few things to point out in this script:

В функции start Обратите внимание на проверку исдисплайопакуе.In the start function, notice the check for IsDisplayOpaque. В этом случае предполагается, что привязка установлена.In this case, we pretend that the Anchor is established. Это обусловлено тем, что в впечатляющих головных гарнитурах не предоставляется способ импорта или экспорта привязок.This is because the immersive headsets do not expose a way to import or export anchors. Однако если мы выполняем на HoloLens, этот скрипт реализует совместное использование привязок между устройствами.If we are running on a HoloLens, however, this script implements sharing anchors between the devices. Устройство, запускающее сеанс, создаст привязку для экспорта.The device that starts the session will create an anchor for exporting. Устройство, которое присоединяется к сеансу, запрашивает привязку с устройства, запустившего сеанс.The device that joins a session will request the anchor from the device that started the session.

ИдетExporting:

Когда пользователь создает сеанс, Нетворкдисковеривисанчорс будет вызывать функцию Унетанчорманажерс Креатеанчор.When a user creates a session, NetworkDiscoveryWithAnchors will call UNETAnchorManagers CreateAnchor function. Рассмотрим Креатеанчор Flow.Let's follow CreateAnchor flow.

Начнем с определенного обслуживания, удалив все данные, которые могли быть собраны для предыдущих привязок.We start by doing some housekeeping, clearing out any data we may have collected for previous anchors. Затем проверяется наличие кэшированной привязки для загрузки.Then we check if there is a cached anchor to load. Данные привязки имеют значение от 5 до 20 МБ, поэтому повторное использование кэшированных привязок может сэкономить на объеме данных, необходимых для передачи по сети.The anchor data tends to be between 5 and 20 MB, so reusing cached anchors can save on the amount of data we need to transfer over the network. Мы посмотрим, как это работает чуть позже.We'll see how this works a bit later. Даже если мы повторно используем привязку, необходимо подготовить данные привязки в случае, если новое соединение с клиентом не имеет привязки.Even if we are reusing the anchor, we need to get the anchor data ready in case a new client joins that doesn't have the anchor.

Говоря о готовности данных привязки, класс Ворлданчортрансфербатч предоставляет функциональные возможности для подготовки данных привязки для отправки на другое устройство или приложение, а также функции для импорта данных привязки.Speaking of getting the anchor data ready, the WorldAnchorTransferBatch class exposes the functionality to prepare anchor data for sending to another device or application and the functionality to import the anchor data. Так как мы используем путь экспорта, мы добавим привязку к Ворлданчортрансфербатч и вызываю функцию Експортасинк.Since we're on the export path, we will add our anchor to the WorldAnchorTransferBatch and call the ExportAsync function. Затем Експортасинк вызывает обратный вызов Вритебуффер при формировании данных для экспорта.ExportAsync will then call the WriteBuffer callback as it generates data for export. Когда все данные экспортированы, Експорткомплете будут вызываться.When all of the data has been exported ExportComplete will be called. В Вритебуффер мы добавляем фрагмент данных в список, который мы храним для экспорта.In WriteBuffer we add the chunk of data to a list we keep for exporting. В Експорткомплете мы преобразуем список в массив.In ExportComplete we convert the list to an array. Также задается переменная Анчорнаме, которая запускает другие устройства для запроса привязки, если они у них нет.The AnchorName variable is also set, which will trigger other devices to request the anchor if they don't have it.

В некоторых случаях привязка не будет экспортироваться или создаст небольшую часть данных, которую мы попробуем снова.In some cases the anchor won't export or will create so little data that we will try again. Здесь мы просто вызываем Креатеанчор.Here we just call CreateAnchor again.

Завершающей функцией в пути экспорта является Анчорфаундремотели.A final function in the export path is AnchorFoundRemotely. Когда другое устройство находит привязку, это устройство будет сообщать узлу, и узел будет использовать его в качестве сигнала о том, что привязка является хорошей привязкой и может быть кэширована.When another device finds the anchor, that device will tell the host, and the host will use that as a signal that the anchor is a "good anchor" and can be cached.

ПадутImporting:

Когда HoloLens присоединяется к сеансу, ему необходимо импортировать привязку.When a HoloLens joins a session, it needs to import an anchor. В функции Update Унетанчорманажер запрос Анчорнаме.In UNETAnchorManager's Update function, the AnchorName is polled. При изменении имени привязки начинается процесс импорта.When the anchor name changes, the import process begins. Сначала мы пытаемся загрузить привязку с указанным именем из локального хранилища привязки.First, we try to load the anchor with the specified name from the local anchor store. Если у нас уже есть, мы можем использовать его, не загружая данные повторно.If we already have it, we can use it without downloading the data again. Если у нас нет, мы вызываем Ваитфоранчор, который начнет загрузку.If we don't have it, then we call WaitForAnchor which will initiate the download.

По завершении загрузки вызывается NetworkTransmitter_dataReadyEvent.When the download is completed, NetworkTransmitter_dataReadyEvent is called. Это подаст циклу обновления вызов Импортасинк с загруженными данными.This will signal the Update loop to call ImportAsync with the downloaded data. Импортасинк будет вызывать Импорткомплете по завершении процесса импорта.ImportAsync will call ImportComplete when the import process is complete. Если импорт выполнен успешно, привязка будет сохранена в локальном хранилище проигрывателя.If the import is successful, the anchor will be saved in the local player store. PlayerController.cs фактически вызывает Анчорфаундремотели, чтобы сообщить узлу о том, что установлена хорошая привязка.PlayerController.cs actually makes the call to AnchorFoundRemotely to let the host know that a good anchor has been established.

Наслаждайтесь ходом выполненияEnjoy your progress

На этот раз пользователь с HoloLens будет размещать сеанс с помощью кнопки запустить сеанс в пользовательском интерфейсе.This time a user with a HoloLens will host a session using the start session button in the UI. Другие пользователи, как в HoloLens, так и в головной гарнитуре, будут выбирать сеанс, а затем нажать кнопку присоединить сеанс в пользовательском интерфейсе.Other users, both on HoloLens or an immersive headset, will select the session and then select the join session button in the UI. Если у вас есть несколько пользователей с устройствами HoloLens, они будут иметь красные облака в своих головах.If you have multiple people with HoloLens devices, they will have red clouds over their heads. Также будет отображаться синий облако для каждой иммерсивного гарнитуры, но синие облака не будут выставляться над гарнитурами, так как гарнитуры не пытаются найти то же пространство координат мира, что и устройства HoloLens.There will also be a blue cloud for each immersive headset, but the blue clouds will not be above the headsets, as the headsets are not trying to find the same world coordinate space as the HoloLens devices.

Эта точка проекта является автономным приложением для управления доступом. Это не делает ничего сложного и может стать базовым.This point in the project is a contained sharing application; it doesn't do very much, and could act as a baseline. В следующих главах мы начнем создавать интерфейс для людей.In the next chapters, we will start building an experience for people to enjoy. Дополнительные рекомендации по проектированию с общим опытом см. здесь.To get further guidance on shared experience design, go here.

Глава 4 — иммерсивное и телепереносChapter 4 - Immersion and teleporting

ЗадачиObjectives

Применяйте интерфейс к каждому типу устройства смешанной реальности.Cater the experience to each type of mixed reality device.

Что будет построеноWhat we will build

Мы будем обновлять приложение, чтобы разместить впечатляющие пользователи гарнитуры по острову с иммерсивное представлением.We will update the application to put immersive headset users on the island with an immersive view. Пользователи HoloLens по-прежнему будут иметь представление о острове с высоты птичьего полета.HoloLens users will still have the bird's eye view of the island. Пользователи каждого типа устройств могут видеть других пользователей по мере их появления в мире.Users of each device type can see other users as they appear in the world. Например, увлекательные пользователи с наушниками могут видеть другие аватары на других путях, и они видят пользователей HoloLens как гигантские облака выше.For instance, immersive headset users can see the other avatars on other paths on the island, and they see the HoloLens users as giant clouds above the island. Для пользователей с головной гарнитурой также будет отображаться курсор пользователя HoloLens, если пользователь HoloLens просматривает остров.Immersive headset users will also see the cursor of the HoloLens user's gaze ray if the HoloLens user is looking at the island. Пользователи HoloLens увидят аватар по острову, который представляет каждого иммерсивного пользователя гарнитуры.HoloLens users will see an avatar on the island to represent each immersive headset user.

Обновленные данные для иммерсивного устройства:Updated Input for the Immersive device:

  • Кнопки левого и правого амортизатора на контроллере Xbox поворачивают проигрывательThe left bumper and right bumper buttons on the Xbox controller rotate the player
  • При нажатии кнопки Y на контроллере Xbox будет включен курсор телепортируйтесь .Holding the Y button on the Xbox controller will enable a teleport cursor. Если в курсоре имеется индикатор в виде вращающейся стрелки, то при отпускании кнопки Y вы будете перенесены в расположение курсора.If the cursor has a spinning arrow indicator when you release the Y button, you will be teleported to the cursor's location.

ШагиSteps

  • Добавление Микседреалитителепорт в МикседреалитикамерапарентAdd MixedRealityTeleport to MixedRealityCameraParent
    • В списке Иерархия выберите усланд.In Hierarchy, select Usland.
    • В инспекторе включите Управление уровнем.In Inspector, enable Level Control.
    • В списке Иерархия выберите микседреалитикамерапарент.In Hierarchy, select MixedRealityCameraParent.
    • В инспекторе щелкните Добавить компонент.In Inspector, click Add Component.
    • Введите Смешанная реальность телепортируйтесь и выберите ее.Type Mixed Reality Teleport and select it.

Продвигаясь вглубь в кодDigging into the code

Впечатляющие пользователи гарнитуры будут подключены к компьютерам с помощью кабеля, но наш остров больше, чем кабель.Immersive headset users will be tethered to their PCs with a cable, but our island is larger than the cable is long. Чтобы компенсировать, нам нужна возможность перемещать камеру независимо от движения пользователя.To compensate, we need the ability to move the camera independently of the user's motion. Дополнительные сведения о проектировании приложения смешанной реальности (в определенном самодвижении и локомотион) см. на странице "комфортная ".Please see the comfort page for more information about designing your mixed reality application (in particular self motion and locomotion).

Чтобы описать этот процесс, полезно определить два условия.In order to describe this process it will be useful to define two terms. Во первых, Долли будет объектом, который перемещает камеру независимо от пользователя.First, dolly will be the object that moves the camera independently from the user. Дочерний объект Game объекта Долли будет основной камерой.A child game object of the dolly will be the main camera. Основная камера подключена к заголовку пользователя.The main camera is attached to the user's head.

На панели проект перейдите к ассетс\апппрефабс\суппорт\скриптс\гамелогик и дважды щелкните MixedRealityTeleport.CS.In the project panel, navigate to Assets\AppPrefabs\Support\Scripts\GameLogic and double-click on MixedRealityTeleport.cs.

Микседреалитителепорт имеет два задания.MixedRealityTeleport has two jobs. Во первых, он обрабатывает поворот с помощью амортизаторов.First, it handles rotation using the bumpers. В функции Update мы будем опрашивать "Буттонуп" на Лефтбумпер и Ригхтбумпер.In the update function we poll for 'ButtonUp' on LeftBumper and RightBumper. Жетбуттонуп возвращает значение true только в первом кадре после нажатия кнопки.GetButtonUp only returns true on the first frame a button is up after having been down. Если одна из кнопок была вызвана, то мы понимаем, что пользователь должен повернуть.If either button had been raised, then we know the user needs to rotate.

При повороте мы провыцветание и поворачивайте с помощью простого сценария, именуемого «выцветание».When we rotate we do a fade out and fade in using a simple script called 'fade control'. Мы делаем это, чтобы пользователь не мог увидеть неестественное перемещение, что может привести к дискомфорт.We do this to prevent the user from seeing an unnatural movement which could lead to discomfort. Эффект затухания и исчезновения довольно прост.The fade in and out effect is fairly simple. У нас есть черновая масть перед основной камерой.We have a black quad hanging in front of the main camera. При переходе в альфа-значение с 0 на 1.When fading out we transition the alpha value from 0 to 1. Это постепенно приводит к тому, что черные пикселы из четырех удаляются и скрывают все, что находится за ними.This gradually causes the black pixels of the quad to render and obscure anything behind them. При переходе в обратное значение альфа-канала возвращается к нулю.When fading back in we transition the alpha value back to zero.

При вычислении вращения Обратите внимание, что мы вращающим Долли , но вычислим поворот вокруг основной камеры.When we calculate the rotation, note that we are rotating our dolly but calculating the rotation around the main camera. Это важно, так как когда Основная камера находится далеко от 0, 0, 0, менее точное вращение вокруг доллиа становится с точки зрения пользователя.This is important as the farther the main camera is away from 0,0,0, the less accurate a rotation around the dolly would become from the point of view of the user. На самом деле, если не вращается вокруг положения камеры, пользователь будет перемещаться по дуге вокруг Долли , а не при повороте.In fact, if you do not rotate around the camera position, the user will move on an arc around the dolly rather than rotating.

Второе задание для Микседреалитителепорт заключается в обработке перемещения Долли.The second job for MixedRealityTeleport is to handle moving the dolly. Это делается в Сетворлдпоситион.This is done in SetWorldPosition. Сетворлдпоситион принимает нужную позицию мира, позицию, где пользователь хочет перЦиеве, что они покрывают.SetWorldPosition takes the desired world position, the position where the user wants to percieve that they inhabit. Нам нужно разместить наш Долли в этой позиции минус локальное расположение основной камеры, так как это смещение будет добавлено в каждый кадр.We need to put our dolly at that position minus the local position of the main camera, as that offset will be added each frame.

Второй скрипт вызывает Сетворлдпоситион.A second script calls SetWorldPosition. Давайте взглянем на этот сценарий.Let's look at that script. На панели проект перейдите к ассетс\апппрефабс\суппорт\скриптс\гамелогик и дважды щелкните TeleportScript.CS.In the project panel, navigate to Assets\AppPrefabs\Support\Scripts\GameLogic and double-click on TeleportScript.cs.

Этот сценарий является немного более сложным, чем Микседреалитителепорт.This script is a little more involved than MixedRealityTeleport. Сценарий проверяет наличие кнопки Y на контроллере Xbox, которую необходимо удерживать.The script is checking for the Y Button on the Xbox controller to be held down. Пока кнопка удерживается, отображается курсор телепортируйтесь и сценарий приводит луч к положению пользователя.While the button is held down a teleport cursor is rendered and the script casts a ray from the user's gaze position. Если этот луч конфликтует с той поверхностью, которая больше или меньше направлена, поверхность будет считаться хорошей для телепортироваться к, а анимация на курсоре телепортируйтесь будет включена.If that ray collides with a surface that is more or less pointing up, the surface will be considered a good surface to teleport to, and the animation on the teleport cursor will be enabled. Если луч не конфликтует с поверхностью, наведя на нее больше или меньше, то анимация курсора будет отключена.If the ray does not collide with a surface more or less pointing up, then the animation on the cursor will be disabled. Когда кнопка Y выдается, а вычисленная точка луча является допустимой позицией, скрипт вызывает Сетворлдпоситион с положением, пересекающимся с лучом.When the Y button is released and the calculated point of the ray is a valid position, the script calls SetWorldPosition with the position the ray intersected.

Наслаждайтесь ходом выполненияEnjoy your progress

На этот раз необходимо найти друга.This time you'll need to find a friend.

Опять же, пользователю с HoloLens будет размещен сеанс.Once again, a user with the HoloLens will host a session. Другие пользователи будут присоединяться к сеансу.Other users will join the session. Приложение поместит первых трех пользователей, чтобы присоединиться к увлекательной гарнитуре по одному из трех путей на самом острове.The application will place the first three users to join from an immersive headset on one of the three paths on the island. В этом разделе вы можете изучить остров.Feel free to explore the island in this section.

Сведения для уведомления:Details to notice:

  1. Вы видите лица в облаках, которые помогают иммерсивное пользователю видеть направление, которое ищет пользователь HoloLens.You can see faces in the clouds, which helps an immersed user see which direction a HoloLens user is looking.
  2. Аватары на острове имеют горловины, которые поворачиваются.The avatars on the island have necks that rotate. Они не следуют тем, что делает пользователь, в реальности (у нас нет этой информации), но она делает неприятной опыт.They won't follow what the user is doing is real reality (we don't have that information) but it makes for a nice experience.
  3. Если пользователь HoloLens просматривает остров, то в иммерсивное пользователи могут видеть свой курсор.If the HoloLens user is looking at the Island, the immersed users can see their cursor.
  4. Облака, представляющие тени, приведенные пользователем HoloLens.The clouds that represent the HoloLens users cast shadows.

Глава 5-заключениеChapter 5 - Finale

ЗадачиObjectives

Создайте интерактивный интерфейс совместной работы между двумя типами устройств.Create a collaborative interactive experience between the two device types.

Что будет построеноWhat we will build

Основываясь на главе 4, когда пользователь с впечатляющим головным телефоном приближается к головоломке по острову, пользователи HoloLens получат всплывающую подсказку с Советом головоломки.Building on chapter 4, when a user with an immersive headset gets near a puzzle on the island, the HoloLens users will get a tool tip with a clue to the puzzle. После того, как все пользователи с головным телефоном получит свои головоломки и появятся на "готовой панели" в Rocket комнате, Rocket запустится.Once all of the immersive headset users get past their puzzles and onto the "ready pad" in the rocket room, the rocket will launch.

ШагиSteps

  • В списке Иерархия выберите усланд.In Hierarchy, select Usland.
  • В окне инспектора на панели Управление уровнями установите флажок включить совместную работу.In Inspector, in Level Control, check Enable Collaboration.

Продвигаясь вглубь в кодDigging into the code

Теперь давайте взглянем на LevelControl.cs.Now let us look at LevelControl.cs. Этот сценарий является ядром логики игры и поддерживает состояние игры.This script is the core of the game logic and maintains the game state. Поскольку это многопользовательская игра, использующая УНЕТ, нам нужно понять, как потоки данных, как минимум, достаточно для изменения этого руководства.Since this is a multiplayer game using UNET we need to understand how data flows, at least well enough to modify this tutorial. Более полный обзор УНЕТ см. в документации Unity.For a more complete overview of UNET, please refer to Unity's documentation.

На панели проект перейдите к ассетс\апппрефабс\суппорт\скриптс\гамелогик и дважды щелкните LevelControl.CS.In the project panel, navigate to Assets\AppPrefabs\Support\Scripts\GameLogic and double-click on LevelControl.cs.

Давайте посмотрим, как иммерсивное гарнитура означает, что они готовы к запуску Rocket.Let us understand how an immersive headset indicates that they are ready for the rocket launch. Готовность к запуску Rocket передается путем установки одного из трех логических значений в виде списка логических значений, соответствующих трем путям по острову.Rocket Launch readiness is communicated by setting one of three bools in a list of bools that correspond to the three paths on the island. Логическое значение пути задается, когда пользователь, назначенный контуру, находится поверх коричневой панели внутри Rocket комнаты.A path's bool will be set when the user assigned to the path is on top of the brown pad inside the rocket room. Итак, теперь с подробными сведениями.Okay, now to the details.

Мы начнем с функции Update ().We will start in the Update() function. Обратите внимание, что имеется функция "Памятка по".You will note that there is a 'cheat' function. Мы использовали это в разработке для тестирования последовательности запуска и сброса Rocket.We used this in development to test the rocket launch and reset sequence. Он не работает в многопользовательском интерфейсе.It won't work in the multi user experience. Надеюсь, в момент, когда вы усвоить следующую невыполненную работу, вы можете сделать это.Hopefully by the time you internalize the following infromation you can make it work. После того, как мы пропроверяем, следует ли памятка по, мы проверяем, находится ли локальный игрок в процессе погружения.After we check to see if we should cheat, we check to see if the local player is immersed. Мы хотим сосредоточиться на том, как мы нашли, что мы будем на цель.We want to focus on how we find that we're at the goal. Внутри проверки if (иммерсивного) существует вызов Чеккгоал, который скрывается за логическим значением енаблеколлаборатион .Inside of the if (Immersed) check, there is a call to CheckGoal hiding behind the EnableCollaboration bool. Это соответствует флажку, установленному при выполнении шагов, описанных в этой главе.This corresponds to the checkbox you checked while completing the steps for this chapter. Внутри Енаблеколлаборатион мы видим вызов Чеккгоал ().Inside of EnableCollaboration we see a call to CheckGoal().

Чеккгоал выполняет некоторые математические операции, чтобы узнать, не занимается ли она на панели.CheckGoal does some math to see if we are more or less standing on the pad. Когда мы будем, отладка. log приступил к цели, а затем мы вызываем "Сендатгоалмессаже ()".When we are, we Debug.Log "Arrived at goal" and then we call 'SendAtGoalMessage()'. В Сендатгоалмессаже мы вызываем playerController. Сендатгоал.In SendAtGoalMessage we call playerController.SendAtGoal. Чтобы сэкономить время, вот код:To save you some time, here's the code:

private void CmdSendAtGoal(int GoalIndex)
{
    levelState.SetGoalIndex(GoalIndex);
}
public void SendAtGoal(int GoalIndex)
{
    if (isLocalPlayer)
    {
        Debug.Log("sending at goal " + GoalIndex);
        CmdSendAtGoal(GoalIndex);
    }
}

Обратите внимание, что Сендатгоалмессаже вызывает Кмдсендатгоал, который вызывает Левелстате. Сетгоалиндекс, который возвращается в LevelControl.cs.Note that SendAtGoalMessage calls CmdSendAtGoal, which calls levelState.SetGoalIndex, which is back in LevelControl.cs. На первый взгляд это кажется странным.At first glance this seems strange. Почему бы не просто вызвать Сетгоалиндекс, а не нестранный маршрут через контроллер проигрывателя?Why not just call SetGoalIndex rather than this strange routing through the player controller? Причина заключается в том, что мы УНЕТ модель данных, которая использует для синхронизации данных. Чтобы предотвратить обмана и пробуксовка, УНЕТ требует, чтобы у каждого объекта был пользователь, обладающий полномочиями на изменение синхронизированных переменных.The reason is that we are conforming to the data model UNET uses to keep data in sync. To prevent cheating and thrashing, UNET requires that each object has a user who has authority to change the synchronized variables. Кроме того, только узел (пользователь, запустивший сеанс) может изменять данные напрямую.Further, only the host (the user that started the session) can change data directly. Пользователи, не являющиеся узлами, но обладающие полномочиями, должны отправить команду на узел, который изменит переменную.Users who are not the host, but have authority, need to send a 'command' to the host which will change the variable. По умолчанию узел имеет полномочия для всех объектов, за исключением того объекта, порожденного для представления пользователя.By default the host has authority over all objects, except for the object spawned to represent the user. В нашем случае у этого объекта есть сценарий playercontroller.In our case this object has the playercontroller script. Существует способ запросить полномочия для объекта, а затем внести изменения, но мы решили использовать тот факт, что у контроллера игрока есть самостоятельный центр и маршрутизация команд через контроллер проигрывателя.There is a way to request authority for an object and then make changes, but we choose to leverage the fact that the player controller has self authority and route commands through the player controller.

Сказал другой способ, когда мы обнаружили себя на нашей цели, игроку нужно сообщить ведущему приложению, и узел сообщит всем остальным.Said another way, when we've found ourselves at our goal, the player needs to tell the host, and the host will tell everyone else.

Вернемся к LevelControl.cs, Взгляните на Сетгоалиндекс.Back in LevelControl.cs look at SetGoalIndex. Здесь мы назначим значение значения в синклист (Атгоал).Here we are setting the value of a value in a synclist (AtGoal). Помните, что в контексте узла мы делаем это.Remember that we are in the context of the host while we do this. Как и команда, RPC — это то, что может выдать узел, что приведет к тому, что все клиенты будут запускать некоторый код.Similar to a command, an RPC is something the host can issue that will cause all clients to run some code. Здесь мы вызываем "Рпкчеккаллгоалс".Here we call 'RpcCheckAllGoals'. Каждый клиент будет отдельно проверять, установлены ли все три Атгоалс, и если да, запустите Rocket.Each client will individually check to see if all three AtGoals are set, and if so, launch the rocket.

Наслаждайтесь ходом выполненияEnjoy your progress

Основываясь на предыдущей главе, мы будем запускать сеанс, как и раньше.Building on the previous chapter, we will start the session as before. На этот раз, когда пользователи в иммерсивное гарнитуре появятся в "дверце" на пути, появится всплывающая подсказка, которая может видеть только пользователи HoloLens.This time as the users in the immersive headset get to the "door" on their path, a tooltip will appear that only the HoloLens users can see. Пользователи HoloLens несут ответственность за передачу этой информации пользователям в иммерсивное гарнитуру.The HoloLens users are responsible for communicating this clue to the users in the immersive headset. Rocket запустится, когда каждый Аватар пойдет на соответствующую коричневую панель в о вулканах.The rocket will launch to space once each avatar has stepped on its corresponding brown pad inside the volcano. Сцена будет сброшена через 60 секунд, что позволит выполнить ее снова.The scene will reset after 60 seconds so you can do it again.

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