Старший разработчик ПО
Узнайте, как закреплять и сохранять 3D-объекты в реальном мире с помощью Unity и Android XR. На этом занятии мы рассмотрим фреймворк Spatial Entities, облачные якоря и Geospatial API, а также покажем, как создавать контекстно-зависимые приложения, которые запоминают физическое размещение и синхронизируют пространственные данные добавление пользователей между сеансами.
Мы изучим архитектуру пространственных объектов, поймем, как привязывать цифровые активы к физическим объектам, поверхностям и географическим местоположениям. Вы узнаете, как в Unity создавать карты пространств, сохранять контент между сеансами и разрабатывать общие AR/XR-проекты с учетом местоположения.
TrySaveAnchorAsync и перезагрузить, используя сериализованные GUID.Расшифровка
Теперь
Здравствуйте!
Это курс "Проектирование пространственного контента на 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.
Есть и другие функции, которые не упомянуты на этом слайде.
Плоскости и якоря считаются отслеживаемыми, поскольку они расширяют класс 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-якорь.
Думаю, этого достаточно.
Эти функции позволяют легко управлять как локальными, так и постоянными привязками.
Поэтому отслеживание якорей – довольно ресурсоемкая задача для большинства платформ дополненной реальности.
При работе с привязками рекомендуется: не создавать несколько привязок слишком близко друг к другу; по возможности использовать существующую привязку вместо создания новой; удалять привязки, которые больше не используются; если вы включили другую функцию дополненной реальности, чтобы рассчитать нужную позу для привязки, отключить эту функцию после успешного создания привязки.
А теперь я передаю слово Леване.
Спасибо, Дженнифер.
Далее я расскажу о вкладе 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 позволяет точно отслеживать геопозицию с помощью 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.
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);
}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;
}async void LoadAnchorAsync(ARAnchorManager manager, SerializableGuid guid) {
var result = await manager.TryLoadAnchorAsync(guid);
if (result.status.IsError()) {
// handle error
return;
}
ARAnchor anchor = result.value;
}void Awake() {
planeManager = GetComponent<ARPlaneManager>();
planeManager.enabled = false;
boundingBoxManager = GetComponent<ARBoundingBoxManager>();
boundingBoxManager.enabled = false;
permissionUtil = GetComponent<AndroidXRPermissionUtil>();
}
void OnEnable() {
StartCoroutine(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;
}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.
}
}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;
}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);
}
}
}// 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.
}
}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.
}
}
}