Настройка плоскостного трекинга и привязки объектов в AR играх

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

От иммерсивных приложений до игровых миров и 3D-сцен

Наша выделенная команда для VR/AR/MR-разработки, Unity-продакшна и 3D-моделирования и анимации с собственными кейсами и презентациями.

Посетить персонализированный сайт
Показано 1 из 1 услугВсе 242 услуг
Настройка плоскостного трекинга и привязки объектов в AR играх
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы
Наши компетенции
Какие этапы разработки игры?
Последние работы
  • image_games_mortal_motors_495_0.webp
    Разработка игры для компании Mortal Motors
    671
  • image_games_a_turnbased_strategy_game_set_in_a_fantasy_setting_with_fire_and_sword_603_0.webp
    Пошаговая стратегия в фэнтези сеттинге With Fire And Sword
    860
  • image_games_second_team_604_0.webp
    Разработка игры для компании Second term
    490
  • image_games_phoenix_ii_606_0.webp
    3D-анимация — тизер для игры phoenix 2.
    533

tags: [vr-ar]

Настройка плоскостного трекинга и привязки объектов в AR играх

AR Foundation в Unity даёт доступ к ARPlaneManager и ARAnchorManager — и именно здесь начинается большинство проблем. Плоскость задетектирована, объект размещён, игрок двигается — и через три шага виртуальный стол уже висит в воздухе в полуметре от поверхности. Либо хуже: ARPlane обновился, но якорь (ARAnchor) остался привязан к старым координатам, и объект начинает «дрейфовать» по комнате.

Это не баг AR Foundation. Это неправильная архитектура сцены.

Почему якоря отвязываются от плоскостей

Главная ошибка — крепить объект напрямую к ARPlane.transform, а не к ARAnchor, привязанному к этой плоскости. ARPlane обновляет свою геометрию при каждом рефреше трекинга: центр смещается, нормаль пересчитывается. Объект, прицепленный к трансформу плоскости как дочерний, просто следует за этим хаосом.

Правильная цепочка: вызвать ARAnchorManager.AttachAnchor(plane, pose), получить ARAnchor с его собственным стабильным трансформом, и уже к нему крепить игровой объект. ARAnchor система трекинга обновляет независимо от геометрии плоскости — его позиция корректируется с учётом IMU-данных и переоценки карты пространства, а не просто пересчитывается вместе с мешем плоскости.

Второй уровень проблем — TrackingState. Якорь может уйти в TrackingState.Limited или вовсе в None, если устройство потеряло визуальные ориентиры. Нужно подписываться на ARAnchorManager.anchorsChanged и обрабатывать переход между состояниями: прятать объект, показывать индикатор «трекинг потерян», восстанавливать позицию когда TrackingState вернётся в Tracking. Большинство проектов это не делают — пользователь видит объект, который завис на последней известной позиции и не реагирует на движение.

Детектирование плоскостей: что реально работает

ARKit на iOS и ARCore на Android используют разные алгоритмы детектирования плоскостей, и это видно в поведении. ARKit агрессивнее расширяет плоскость — даже при частичной видимости поверхности он достраивает её гипотетические границы. ARCore консервативнее: плоскость растёт только там, где было реальное покрытие feature points.

Для игровых сценариев это значит: если игра требует размещения объекта до того, как пользователь обошёл всю поверхность, на Android нужно либо снижать требования к минимальному размеру плоскости в ARPlaneManager.requestedDetectionMode, либо реализовывать принудительное размещение с визуальным предупреждением. Ставить одинаковые пороги детектирования для обеих платформ — гарантированно плохой UX на одной из них.

Отдельная тема — вертикальные плоскости (PlaneDetectionMode.Vertical). На большинстве Android-устройств вертикальный трекинг значительно нестабильнее горизонтального. Игры, предполагающие размещение объектов на стенах, должны тестироваться на реальном железе, а не в ARCore Emulator — симулятор не воспроизводит шум IMU-данных и реальный дрейф.

Как это делаем на практике

Типичный кейс: мобильная AR-игра, где игрок расставляет башни на полу комнаты. Основная проблема на этапе прототипа — башни «плавали» при движении камеры. Причина — объекты крепились к ARPlane через SetParent, трекинг плоскости обновлял меш, и дочерние объекты смещались вместе с новым центром.

Решение: переход на ARAnchor-архитектуру. Каждая башня при размещении получает собственный якорь через AttachAnchor. Якорь добавляется в словарь Dictionary<ARAnchor, TowerObject> — при срабатывании anchorsChanged.removed башня получает уведомление и переходит в «ненадёжное» состояние с визуальным индикатором. При added (если это был known anchor из сохранённой сессии) — восстанавливается.

Для сохранения якорей между сессиями используем ARWorldMap (ARKit) или Cloud Anchors API (ARCore/ARKit через AR Foundation Samples). Cloud Anchors позволяют якорю пережить перезапуск приложения и даже работать между разными устройствами — это основа для многопользовательского AR.

Этапы работы над задачей

  1. Аудит текущей архитектуры — проверяем, как объекты привязаны к плоскостям, есть ли обработка TrackingState, как ведёт себя сцена при потере трекинга
  2. Настройка ARPlaneManager — режимы детектирования, фильтрация по минимальному размеру, визуализация плоскостей для дебага
  3. Реализация ARAnchor-архитектуры — переход от parent-child к якорям, обработка жизненного цикла якорей
  4. Тестирование на целевых устройствах — ARKit (iPhone 12+) и ARCore (флагманы + mid-range Android)
  5. Опциональная интеграция Cloud Anchors — если нужна персистентность между сессиями
Масштаб задачи Ориентировочные сроки
Аудит + фикс существующей архитектуры 2–5 дней
Настройка с нуля для новой сцены 3–7 дней
Интеграция Cloud Anchors + мультиплеер 2–4 недели

Типичные ошибки при настройке трекинга

Не обрабатывается LimitedTrackingReason.ExcessiveMotion. При быстром движении камеры ARCore переходит в Limited, и объекты начинают «прыгать». Правильная реакция — заморозить позицию объекта на время потери трекинга, не пересчитывать физику, и восстановить плавно через Lerp после возврата в Tracking.

ARRaycastManager используется без проверки типа хита. ARRaycastHit.trackable может быть как ARPlane, так и ARPoint (feature point). Для размещения объектов на поверхностях нужно фильтровать только TrackableType.PlaneWithinPolygon — иначе пользователь будет «размещать» объекты в воздухе на feature points.

Слишком агрессивный ARPlane меш в продакшене. В дебаге удобно видеть всю геометрию плоскостей, но в финальной игре меш плоскостей либо скрывается полностью, либо заменяется декоративным вариантом. Стандартный ARFeatheredPlaneMeshVisualizer из AR Foundation Samples — хорошая отправная точка.