Android XR

Проектирование пространственного контента на Android XR с помощью Unity

Колонки

  • Левана Чен (Levana Chen)

    Разработчик ПО

  • Дженнифер Стэнтон

    Старший разработчик ПО

О приложении

О выступлении

Узнайте, как закреплять и сохранять 3D-объекты в реальном мире с помощью Unity и Android XR. На этом занятии мы рассмотрим фреймворк Spatial Entities, облачные якоря и Geospatial API, а также покажем, как создавать контекстно-зависимые приложения, которые запоминают физическое размещение и синхронизируют пространственные данные добавление пользователей между сеансами.

Мы изучим архитектуру пространственных объектов, поймем, как привязывать цифровые активы к физическим объектам, поверхностям и географическим местоположениям. Вы узнаете, как в Unity создавать карты пространств, сохранять контент между сеансами и разрабатывать общие AR/XR-проекты с учетом местоположения.

Сводка

  • AR Foundation предоставляет единый API для создания скриптов на разных платформах XR с помощью расширений OpenXR. Он позволяет представлять и запрашивать объекты реального мира, такие как плоскости и сетки.
  • Постоянные привязки стабилизируют цифровой контент между сеансами и перезапусками устройств. Вы можете сохранить их с помощью TrySaveAnchorAsync и перезагрузить, используя сериализованные GUID.
  • Фреймворк Spatial Entities заменяет расширения для отслеживания, чтобы обеспечить кросс-платформенную поддержку и более высокую производительность при отслеживании таких элементов, как ограничивающие рамки и маркеры.
  • Компоненты менеджера должны быть отключены, пока не будут предоставлены разрешения Android XR. Это позволяет избежать сбоев инициализации подсистемы, вызванных ограниченным доступом к конфиденциальным данным среды.
  • Geospatial API использует сервисы Google Cloud ARCore и VPS для размещения контента в реальных местах на открытом воздухе.

Ресурсы

Gemini Notebook

Темы

  • android-xr
  • единство
  • ar-foundation
  • openxr
  • spatial-entities
  • нижние фиксированные объявления
  • geospatial-api

Расшифровка

Введение и обзор AR Foundation

  • Теперь

  • Здравствуйте!

  • Это курс "Проектирование пространственного контента на Android XR с помощью Unity".

  • Меня зовут Дженнифер Стэнтон.

  • Я работаю в Unity старшим инженером-программистом.

  • Я работаю в команде XR Features, в частности над AR Foundation и связанными пакетами, которые добавляют дополненную и смешанную реальность в Unity.

  • Меня зовут Левана Чен, я работаю в команде Google по игровым движкам XR.

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

  • По словам разработчиков, одна из самых больших сложностей – это поддержка нескольких XR-платформ с одной базой кода.

  • AR Foundation – это высокоуровневый API расширенной реальности от Unity.

  • Вы можете разрабатывать приложения для нескольких XR-платформ, не переписывая код и не управляя несколькими базами кода. Кроме того, у вас будет один API для скриптов, позволяющий добавлять функции дополненной реальности на любую платформу.

  • Это позволяет вам сосредоточиться на создании приложения, игры или другого продукта, а Unity позаботится о деталях платформы за вас.

  • Один из способов, которым AR Foundation достигает этого, – расширения OpenXR.

  • Это набор открытых стандартных API, разработанных Khronos Group.

  • OpenXR также создал пространственные объекты.

  • Это фреймворк для цифрового контента, который позволяет представлять физический мир и взаимодействовать с ним.

  • Пространственные объекты – это унифицированная модель для представления элементов реального мира в виде цифровых объектов.

  • Я рад поделиться с вами последней информацией об AR Foundation, чтобы вы могли начать создавать свои собственные проекты в расширенной реальности.

  • Затем я расскажу о возможностях AR Foundation, которые позволяют цифровому контенту взаимодействовать с реальным миром.

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

  • В конце я расскажу о некоторых функциях, уникальных для Android XR.

Основные функции AR Foundation

  • Итак, некоторые из способов, которыми AR Foundation представляет реальный мир в цифровом виде, — это плоскости.

  • Это плоские поверхности в физической среде, такие как полы, стены, потолки и даже столы и диваны.

  • Сетки – это трехмерные структуры, представляющие геометрию физического мира.

  • А ещё у нас есть способы взаимодействия с реальным миром, трассировка лучей.

  • Они определяют, где луч пересекается с цифровым контентом.

  • Представьте, что это лазерная указка, и вы получаете информацию о том, куда она направлена.

  • Также у нас есть якоря, которые помогают стабилизировать и переместить точку в пространстве.

  • Позже в этой презентации я расскажу о якорях подробнее.

  • Итак, все четыре из них считаются функциями AR Foundation.

  • Есть и другие функции, которые не упомянуты на этом слайде.

  • Плоскости и якоря считаются отслеживаемыми, поскольку они расширяют класс ARTrackable, а их менеджеры отслеживают обновления во время выполнения.

  • Итак, давайте перейдем к самолетам.

  • Для плоскостей у нас есть компонент ARPlane, который обеспечивает идентификацию плоских поверхностей в реальном времени.

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

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

  • Мы также можем прикрепить к плоскости сетчатый коллайдер для обработки физики.

  • Вот пример распознавания плоскости.

  • Это сцена с трассировкой лучей из примеров AR Foundation, запущенная на устройстве Android XR.

  • Она обнаруживает динамические двухмерные многоугольники в реальном времени.

  • Вы можете создать приложение с этой функцией, следуя нашему руководству по настройке проекта или используя один из наших примеров или шаблонов.

  • Далее у нас есть сетки.

  • Сетки – это функция дополненной реальности, которая позволяет создавать 3D-сетки окружающей среды.

  • К сгенерированным сеткам можно прикрепить коллайдер, чтобы цифровой контент мог взаимодействовать с объектами реального мира.

  • Сетки позволяют убедительно перекрывать объекты.

  • Таким образом, виртуальный объект может оказаться за физическим.

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

  • Далее у нас есть трассировка лучей.

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

  • Проецируемый луч может пересекаться с несколькими 3D-объектами в среде.

  • Вы можете настроить луч так, чтобы он попадал только на определенные типы цифрового контента.

  • Например, вы можете настроить его так, чтобы он не сталкивался с плоскостями и пересекался только с сетками.

Настройка пакетов и зависимостей

  • Теперь давайте рассмотрим соответствующие пакеты.

  • Все эти пакеты взаимодействуют друг с другом, чтобы обеспечить полноценную работу XR.

  • Как уже упоминалось, AR Foundation обрабатывает такие функции, как плоскости и привязки.

  • Плагин OpenXR обрабатывает нативные API на различных платформах XR, поэтому вы можете использовать этот пакет, если ваше устройство использует OpenXR.

  • Плагин OpenXR можно использовать вместе с пакетом OpenXR Spatial Entities, чтобы получить доступ к расширениям Spatial Entities. Подробнее об этом мы расскажем позже.

  • Если вы планируете разрабатывать приложения специально для устройств Android XR, например XR-шлемов и проводных XR-очков, вам понадобится пакет Unity OpenXR Android XR.

  • Поскольку все это соответствует шаблону плагина, влияние на ваш код должно быть минимальным.

  • Не все функции доступны во всех пакетах AR Foundation.

  • Например, если вы посмотрите на эту диаграмму, то увидите, что мешинг в настоящее время недоступен в пакете Unity OpenXR Spatial Entities.

  • XR Plug-in Management позволяет управлять функциями OpenXR, выбранными в проекте.

  • Если вы используете редактор Unity, выберите Edit (Изменить), Project Settings (Настройки проекта), а затем XR Plug-in Management (Управление плагинами XR) на боковой панели слева.

  • Здесь вы можете найти функции и группы функций OpenXR, чтобы выбрать, какие из них вы хотите включить в свою сборку.

  • Например, на этом скриншоте показаны все расширения, которые поставляются с пакетом Android XR OpenXR.

  • И затем вы можете смешивать и сопоставлять их с пространственными объектами, например, если вы этого хотите.

  • Итак, перед нами окно Package Manager.

  • Я выделил некоторые пакеты, которые вы можете увидеть в типичной настройке проекта XR.

  • Как видите, у нас есть AR Foundation, о котором уже упоминалось.

  • Также у нас есть плагин OpenXR.

  • У нас есть пакет Android XR.

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

  • А в правом нижнем углу у нас есть ещё несколько пакетов.

  • Composition Layers, которые работают с устройствами OpenXR; Core Utils, очень полезные для всего, что связано с XR; а также XR Hands и XR Interaction Toolkit для получения входных данных, что очень важно.

  • Далее у нас идёт валидация проекта.

  • Это часть XR Plug-in Management.

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

  • Но на этом скриншоте я выделил повторяющиеся функции.

  • Итак, здесь в основном говорится о двух одинаковых функциях, таких как, я думаю, у нас есть привязки, возможно, плоскости и лучи.

  • Пользователь выбрал дубликаты этих функций из нескольких пакетов, и ему предлагается выбрать один из них.

Локальные и постоянные якоря

  • Итак, это подводит нас к локальным якорям и настойчивости.

  • Якоря гарантируют, что цифровой контент останется в нужных местах среды независимо от изменений в состоянии отслеживания сеанса AR.

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

  • А что, если пользователь закроет приложение, а затем снова откроет его и вернется к нему в рамках отдельного сеанса?

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

  • Они сохраняются при перезапуске приложения и устройства.

  • На изображении показан пример постоянных якорей в проекте AR Foundation Samples.

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

  • И это подводит нас к жизненному циклу постоянных привязок.

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

  • а затем сохраняете его в хранилище.

  • После этого вы можете перезапустить приложение и загрузить его из хранилища.

  • Некоторые платформы, включая Android XR, также поддерживают удаление или отмену сохранения якорей.

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

  • В настройках XR Plug-in Management выберите параметр Automatically Load Saved Anchors (Автоматически загружать сохраненные привязки) в функции Spatial Entities: Anchors (Пространственные объекты: привязки).

  • А для сохранения якоря требуется всего несколько строк кода.

  • Сначала мы открываем редактор Unity и проверяем, готова ли сцена, добавляя компонент AR Anchor Manager к игровому объекту XR Origin.

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

  • Итак, перейдём к коду.

  • Чтобы добавить якорь, вызовите метод TryAddAnchorAsync и передайте ему позу, в которой вы хотите разместить якорь.

    async void CreateAnchorAsync(ARAnchorManager manager, Pose pose) {
        var result = await manager.TryAddAnchorAsync(pose);
        if (result.status.IsError()) {
            // handle error
            return;
        }
        var anchor = result.value;
    }
  • Далее мы удаляем якоря.

    void RemoveAnchor(ARAnchorManager manager, ARAnchor anchor) {
        var result = manager.TryRemoveAnchor(anchor.trackableId);
        if (result.status.IsError()) {
            // handle error
            return;
        }
    }
    
    void DestroyAnchorComponent(ARAnchor anchor) {
        Destroy(anchor);
    }
  • И аналогично, это практически одна строка кода.

  • Вы вызываете TryRemoveAnchor и передаете отслеживаемый идентификатор привязки.

  • При создании якоря ему уже был присвоен отслеживаемый идентификатор.

  • И, наконец, TrySaveAnchorAsync.

    async void SaveAnchorAsync(ARAnchorManager manager, ARAnchor anchor) {
        var result = await manager.TrySaveAnchorAsync(anchor);
        if (result.status.IsError()) {
            // handle error
            return;
        }
    
        // Save this value, then return it as an input parameter
        SerializableGuid guid = result.value;
    }
  • В качестве входных данных вы передаете AR-якорь.

  • Эта функция возвращает SerializableGuid, который идентифицирует якорь в постоянном хранилище.

  • Позже вы сможете использовать GUID при загрузке привязки.

  • Теперь перейдем к загрузке фиксированных объявлений.

    async void LoadAnchorAsync(ARAnchorManager manager, SerializableGuid guid) {
        var result = await manager.TryLoadAnchorAsync(guid);
        if (result.status.IsError()) {
            // handle error
            return;
        }
    
        ARAnchor anchor = result.value;
    }
  • В этом случае вызывается функция TryLoadAnchorAsync, и вы передаете сериализованный GUID, полученный ранее.

  • В результате будет возвращен AR-якорь.

  • Думаю, этого достаточно.

  • Эти функции позволяют легко управлять как локальными, так и постоянными привязками.

  • Поэтому отслеживание якорей – довольно ресурсоемкая задача для большинства платформ дополненной реальности.

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

  • А теперь я передаю слово Леване.

Android XR SDK для Unity

  • Спасибо, Дженнифер.

  • Далее я расскажу о вкладе Google в развитие Android XR в Unity.

  • Помимо плагинов Unity OpenXR, о которых рассказала Дженнифер, Google предоставляет Android XR SDK для Unity с дополнительными возможностями, доступными на платформе Android XR.

  • Этот SDK содержит множество функций и пакетов, и в этом докладе мы сосредоточимся на пакете Android XR Extension для Unity.

  • Как и OpenXR Android XR и OpenXR Spatial Entities, пакет Android XR Extension для Unity – это поставщик OpenXR.

  • Архитектура этого пакета выглядит следующим образом, и они могут работать параллельно или независимо.

  • Как и у других поставщиков OpenXR, пакет Google создан на основе стандартного интерфейса OpenXR.

  • Поэтому мы показываем ряд функций для сравнения со всеми другими поставщиками.

  • Это поможет вам решить, когда и почему стоит выбрать один из них.

  • Итак, у вас может возникнуть вопрос об отслеживаемом объекте и маркере пространственного объекта, показанном в этой таблице.

  • Примечание. Для тех, кто уже создавал приложения и работал с Android XR, мы добавили эти функции через расширения, которые работают только на Android XR.

  • А затем, как упомянула Дженнифер, мы работали в открытой группе OpenXR, а затем выпустили расширение Spatial Entities Extension, которое вы видите справа, и обеспечили согласованную и кроссплатформенную работу.

  • В настоящее время мы прекращаем поддержку расширения trackable в пользу фреймворка Spatial Entities.

  • Они не только более эффективны, но и поддерживают кросс-платформенность.

Создание пространственных объектов

  • А теперь давайте подробнее рассмотрим пространственные объекты.

  • Итак, помимо плоскостей, трассировки лучей и якорей, о которых говорила Дженнифер, эта функция также поддерживается поставщиками пространственных объектов, например маркерами, которые могут обнаруживать и декодировать стандартные 2D-штрихкоды и отслеживать их положение в 3D-пространстве, а также изображениями, которые будут распознавать известную 2D-графику и отслеживать ее в 3D-пространстве.

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

  • В следующем примере мы настроим функцию граничной рамки, которая предоставляется пакетом расширений Google.

  • Итак, здесь это представление практически одинаково для всех функций OpenXR.

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

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

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

  • И последнее: вы можете просто создать пример сцены или тестовую сцену.

  • Чтобы получить доступ к отслеживаемому объекту во время выполнения, вы можете просто добавить компонент AR Bounding Box Manager. Он похож на AR Anchor Manager. Затем используйте интерфейс AR Foundation для доступа к нему.

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

  • Вот основное отличие при использовании функции AR Foundation в Android XR.

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

  • Чтобы защитить пользователя, Android XR ограничивает доступ системы к данным, на которые распространяются разрешения.

  • Возможно, вы уже знакомы с этим, например, с обычным вызовом разрешений Android, таким как доступ к камере или доступ к местоположению и тому подобное.

  • Рекомендуется отключить компонент менеджера при запуске, либо в редакторе, как показано справа, либо в скрипте, например в событии Awake.

    void Awake() {
        planeManager = GetComponent<ARPlaneManager>();
        planeManager.enabled = false;
        boundingBoxManager = GetComponent<ARBoundingBoxManager>();
        boundingBoxManager.enabled = false;
        permissionUtil = GetComponent<AndroidXRPermissionUtil>();
    }
    
    void OnEnable() {
        StartCoroutine(WaitForPermissions());
    }
  • После того как вы предоставите все необходимые разрешения, вы сможете включить менеджер из скрипта, как это делает вспомогательный класс WaitForPermissions.

    IEnumerator WaitForPermissions() {
        planeManager.enabled = false;
        boundingBoxManager.enabled = false;
    
        yield return new WaitUntil(() =>
            permissionUtil.AllPermissionGranted());
    
        // Enable after granted permissions and
        // restart subsystems.
        planeManager.enabled = true;
        boundingBoxManager.enabled = true;
    
        // Save permission status.
        permissionGranted = true;
    }
  • Это позволит избежать сбоя инициализации подсистемы из-за недостаточных разрешений.

  • И это особая функция.

  • Как рассказала Дженнифер, для работы с якорями используется AR Foundation. Чтобы расширить возможности якорей в Android XR, мы добавили в пакет новую функцию – общие якоря.

  • Эта функция повторяет возможности функции привязки AR Foundation, а также предлагает дополнительные возможности, такие как геопространственные привязки.

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

  • Дженнифер рассказала нам о создании, сохранении и загрузке якорей, но все это происходило в локальном пространстве, например в гостиной пользователя.

  • Но как насчет остального мира?

  • И как мы могли бы поделиться этим друг с другом?

Geospatial API

  • И здесь на помощь приходит Geospatial API.

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

  • Geospatial API позволяет точно отслеживать геопозицию с помощью VPS (системы виртуального позиционирования), которая похожа на GPS, но использует данные Просмотра улиц, чтобы повысить точность.

  • Если вы уже работали с геопространственными функциями ARCore, то, возможно, знакомы с этим представлением.

  • Чтобы получить доступ к Geospatial API на Android XR, сначала нужно подключиться к серверной части, размещенной на платформе Google Cloud.

  • Поскольку геопространственный бэкенд работает на базе сервиса ARCore в Google Cloud, вы можете выполнить те же действия, чтобы настроить проект Google Cloud с доступом к ARCore API.

  • Все это позволит использовать функцию Android XR Google Cloud, которая предоставляется нашим пакетом расширения.

  • Включив Geospatial API и получив ключ API из облачного проекта Google Cloud, вы можете включить эту функцию и настроить аутентификацию в меню настроек OpenXR, как показано здесь. Также вы можете настроить ее вручную с помощью API скриптов TrySetAuthenticationAsync.

    async Task TrySetAuthentication() {
        googleCloudFeature =
            OpenXRSettings.Instance
                .GetFeature<XRGoogleCloudFeature>();
        var result = await googleCloudFeature
            .TrySetAuthenticationAsync(
                strategy, credential);
        if (result.IsSuccess()) {
            // Ready to use for geospatial tracker.
        } else if (result.IsUnsupported())  {
            // Google Cloud feature is not supported
        } else if (result.IsKeylessError()) {
            // Confirm if keyless has been set up properly.
        } else {
            // Handling other common OpenXR errors.
        }
    }
  • Обратите внимание, что сейчас платформа Android XR поддерживает только аутентификацию с помощью ключа API, но в будущем мы добавим поддержку других учетных данных.

  • После аутентификации вы можете использовать менеджер геопространственных данных для доступа к геопространственным возможностям.

  • Перед интеграцией настоятельно рекомендуется проверить покрытие VPS на Google Картах.

  • Поэтому для использования этой функции у вас должен быть доступ к сети.

  • Итак, XR Geospatial Manager работает аналогично компоненту AR Session, предоставляемому AR Foundation.

  • Поэтому у него есть статическое свойство состояния, которое указывает на поддержку системы и состояние отслеживания геопространственного трекера.

  • Вы можете зарегистрировать событие изменения состояния с помощью обратного вызова, как показано ниже.

    void OnGeospatialStateChanged(XRGeospatialStateChangedEventArgs eventArgs) {
        bool isInitFailed = eventArgs.CurrState == XRGeospatialState.InitializationFailed;
        if (isInitFailed && XRGeospatialManager.InitializationResult.IsCloudAuthError()) {
            // Handle cloud authentication issues.
        } else if (isInitFailed) {
            // Check XRGeospatialManager.InitializationResult for other common OpenXR errors.
        } else {
            // Iterate runtime state change, and handle accordingly.
        }
    }
    
    private void OnEnable() {
        XRGeospatialManager.OnStateChanged += OnGeospatialStateChanged;
    }
  • Когда геопространственное состояние станет запущенным, вы сможете использовать этот экземпляр менеджера для всех следующих функций.

  • Сначала, чтобы проверить доступность VPS для заданного местоположения GPS, мы используем Location API Unity, чтобы получить значение GPS, а затем проверяем доступность VPS.

    async Task CheckVPSAvailability(CancellationToken token) {
        var location = Input.location.lastData;
        try {
            var result = await geospatialManager.TryCheckVPSAvailabilityAsync(
                location.latitude, location.longitude);
            token.ThrowIfCancellationRequested();
            if (result.status.nativeStatusCode == (int)XrResultAndroid.GeospatialCoordinateInvalid) {
                // Invalid coordinates, try with another location.
            } else if (result.status.IsError()) {
                // Handle common OpenXR error: result.status.ToOpenXRStatus()
            }  else if (result.value == XRVPSAvailability.Available)  {
                // You may use this pose to attach geospatial anchors.
                var currentGeospatialPose = new XRGeospatialPose(location);
            }
        }
    }
  • Это замена на случай, если вы не хотите проверять поддержку VPS на карте. Но чтобы проверить статус GPS, вам нужно выйти на улицу.

  • Затем вы также можете преобразовать позу между позой Unity и геопространственной позой с помощью TryLocate.

    // Geospatial Pose -> Unity Pose
    var geospatialPose =
        new XRGeospatialPose(Input.location.lastData);
    if (geospatialManager.TryLocate(
            geospatialPose, out XRPoseResult result)) {
        if (result.IsPositionValid ||
            result.IsPositionTracked) {
            transform.position = result.Pose.position;
        }
        if (result.IsRotationValid ||
            result.IsRotationTracked) {
            transform.rotation = result.Pose.rotation;
        }
    }
    // Unity Pose -> Geospatial Pose
    Pose pose = new Pose(
        transform.position, transform.rotation);
    if (geospatialManager.TryLocate(
          pose, out XRGeospatialPoseResult result)) {
        if (result.IsPositionValid ||
            result.IsRotationValid) {
            // You may use for anchor attachment.
        }
    }
  • Затем, используя результат проверки VPS или преобразования позы, вы можете прикрепить пространственный якорь к заданной геопространственной позе или к известному типу поверхности, например к местности или крыше.

    async void PlaceAnchor(XRGeospatialPose pose) {
        try {
            Result<ARShareableAnchor> anchorResult;
            XRGeospatialSurfaceType typeToPlace = /* Choose your target type */;
            if (typeToPlace == XRGeospatialSurfaceType.Default) {
                anchorResult = geospatialManager.TryAttachGeospatialAnchor(pose);
            } else {
                pose.Altitude = 0;
                anchorResult = await geospatialManager.TryAttachSurfaceAnchorAsync(typeToPlace, pose);
            }
            if (anchorResult.status.IsSuccess()) {
                // ARShareableAnchorManager will track the anchor and update it.
            } else {
                // Handle OpenXR failures.
            }
        }
    }
  • Объединив все эти возможности, вы сможете создавать по-настоящему волшебные пространственные эффекты, в центре которых будет реальный мир.

  • Поэтому мы размещаем стрелку, чтобы направить аудиторию в нужное место в реальном мире.

  • Окей.

  • Android XR SDK – не единственный пакет, который мы предоставляем разработчикам Unity.

  • Google Android XR SDK для Unity теперь также включает Android XR Interaction Framework и пакет Android XR Audio.

  • Мы рады расширить Android XR SDK, добавив поддержку дополнительных функций и пространственных объектов.

Краткое заключение и дополнительные материалы

  • Итак, наше занятие подходит к концу.

  • Вы можете следить за планом развития Unity онлайн, чтобы узнавать о предстоящих изменениях.

  • Не забывайте, что в начале следующего года выйдет Unity 7 – новое поколение Unity.

  • А пока вы можете попробовать эти инструменты и создать проект с помощью шаблона смешанной реальности или взглянуть на примеры проектов AR Foundation на нашем GitHub.

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

  • И спасибо всем вам.

  • Нам не терпится увидеть, что вы создадите с помощью AR Foundation и пространственных объектов на Android XR.

Код

Фрагменты кода

Фрагмент кода на C# в разделе "Локальные якоря и сохранение"
async void CreateAnchorAsync(ARAnchorManager manager, Pose pose) {
    var result = await manager.TryAddAnchorAsync(pose);
    if (result.status.IsError()) {
        // handle error
        return;
    }
    var anchor = result.value;
}
Фрагмент кода на C# в разделе "Локальные привязки и сохранение"
void RemoveAnchor(ARAnchorManager manager, ARAnchor anchor) {
    var result = manager.TryRemoveAnchor(anchor.trackableId);
    if (result.status.IsError()) {
        // handle error
        return;
    }
}

void DestroyAnchorComponent(ARAnchor anchor) {
    Destroy(anchor);
}
Фрагмент кода на C# на 11:00 в разделе "Локальные привязки и сохранение"
async void SaveAnchorAsync(ARAnchorManager manager, ARAnchor anchor) {
    var result = await manager.TrySaveAnchorAsync(anchor);
    if (result.status.IsError()) {
        // handle error
        return;
    }

    // Save this value, then return it as an input parameter
    SerializableGuid guid = result.value;
}
Фрагмент кода на C# на 11:17 в разделе "Локальные привязки и сохранение"
async void LoadAnchorAsync(ARAnchorManager manager, SerializableGuid guid) {
    var result = await manager.TryLoadAnchorAsync(guid);
    if (result.status.IsError()) {
        // handle error
        return;
    }

    ARAnchor anchor = result.value;
}
Фрагмент кода на C# в видео "Разработка с использованием пространственных объектов"
void Awake() {
    planeManager = GetComponent<ARPlaneManager>();
    planeManager.enabled = false;
    boundingBoxManager = GetComponent<ARBoundingBoxManager>();
    boundingBoxManager.enabled = false;
    permissionUtil = GetComponent<AndroidXRPermissionUtil>();
}

void OnEnable() {
    StartCoroutine(WaitForPermissions());
}
Фрагмент кода на C# в видео "Создание приложений с пространственными объектами"
IEnumerator WaitForPermissions() {
    planeManager.enabled = false;
    boundingBoxManager.enabled = false;

    yield return new WaitUntil(() =>
        permissionUtil.AllPermissionGranted());

    // Enable after granted permissions and
    // restart subsystems.
    planeManager.enabled = true;
    boundingBoxManager.enabled = true;

    // Save permission status.
    permissionGranted = true;
}
Фрагмент кода на C# в видео Geospatial API
async Task TrySetAuthentication() {
    googleCloudFeature =
        OpenXRSettings.Instance
            .GetFeature<XRGoogleCloudFeature>();
    var result = await googleCloudFeature
        .TrySetAuthenticationAsync(
            strategy, credential);
    if (result.IsSuccess()) {
        // Ready to use for geospatial tracker.
    } else if (result.IsUnsupported())  {
        // Google Cloud feature is not supported
    } else if (result.IsKeylessError()) {
        // Confirm if keyless has been set up properly.
    } else {
        // Handling other common OpenXR errors.
    }
}
Фрагмент кода на C# в видео Geospatial API (20:24)
void OnGeospatialStateChanged(XRGeospatialStateChangedEventArgs eventArgs) {
    bool isInitFailed = eventArgs.CurrState == XRGeospatialState.InitializationFailed;
    if (isInitFailed && XRGeospatialManager.InitializationResult.IsCloudAuthError()) {
        // Handle cloud authentication issues.
    } else if (isInitFailed) {
        // Check XRGeospatialManager.InitializationResult for other common OpenXR errors.
    } else {
        // Iterate runtime state change, and handle accordingly.
    }
}

private void OnEnable() {
    XRGeospatialManager.OnStateChanged += OnGeospatialStateChanged;
}
Фрагмент кода на C# в видео Geospatial API (20:38)
async Task CheckVPSAvailability(CancellationToken token) {
    var location = Input.location.lastData;
    try {
        var result = await geospatialManager.TryCheckVPSAvailabilityAsync(
            location.latitude, location.longitude);
        token.ThrowIfCancellationRequested();
        if (result.status.nativeStatusCode == (int)XrResultAndroid.GeospatialCoordinateInvalid) {
            // Invalid coordinates, try with another location.
        } else if (result.status.IsError()) {
            // Handle common OpenXR error: result.status.ToOpenXRStatus()
        }  else if (result.value == XRVPSAvailability.Available)  {
            // You may use this pose to attach geospatial anchors.
            var currentGeospatialPose = new XRGeospatialPose(location);
        }
    }
}
Фрагмент кода на C# в видео Geospatial API (21:03)
// Geospatial Pose -> Unity Pose
var geospatialPose =
    new XRGeospatialPose(Input.location.lastData);
if (geospatialManager.TryLocate(
        geospatialPose, out XRPoseResult result)) {
    if (result.IsPositionValid ||
        result.IsPositionTracked) {
        transform.position = result.Pose.position;
    }
    if (result.IsRotationValid ||
        result.IsRotationTracked) {
        transform.rotation = result.Pose.rotation;
    }
}
Фрагмент кода на C# в видео "Geospatial API"
// Unity Pose -> Geospatial Pose
Pose pose = new Pose(
    transform.position, transform.rotation);
if (geospatialManager.TryLocate(
      pose, out XRGeospatialPoseResult result)) {
    if (result.IsPositionValid ||
        result.IsRotationValid) {
        // You may use for anchor attachment.
    }
}
Фрагмент кода на C# в видео Geospatial API (21:11)
async void PlaceAnchor(XRGeospatialPose pose) {
    try {
        Result<ARShareableAnchor> anchorResult;
        XRGeospatialSurfaceType typeToPlace = /* Choose your target type */;
        if (typeToPlace == XRGeospatialSurfaceType.Default) {
            anchorResult = geospatialManager.TryAttachGeospatialAnchor(pose);
        } else {
            pose.Altitude = 0;
            anchorResult = await geospatialManager.TryAttachSurfaceAnchorAsync(typeToPlace, pose);
        }
        if (anchorResult.status.IsSuccess()) {
            // ARShareableAnchorManager will track the anchor and update it.
        } else {
            // Handle OpenXR failures.
        }
    }
}