Налаштування плоскостного трекінгу та привязки об'єктів в 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 (якщо це був відомий якорь із збереженої сесії) – відновлюється.
Для збереження якорів між сеансами використовуємо ARWorldMap (ARKit) або Cloud Anchors API (ARCore/ARKit через AR Foundation Samples). Cloud Anchors дозволяють якорю пережити перезапуск приложення та навіть працювати між різними пристроями – це основа для багатокористувацького AR.
Етапи роботи над завданням
-
Аудит поточної архітектури – перевіряємо, як об'єкти привязані до площин, наявність обробки
TrackingState, як сцена поводиться при втраті трекінгу -
Налаштування
ARPlaneManager– режими детектування, фільтрація за мінімальним розміром, візуалізація площин для дебагу -
Реалізація
ARAnchor-архітектури – перехід від parent-child до якорів, обробка життєвого циклу якорів - Тестування на цільових пристроях – ARKit (iPhone 12+) та ARCore (флагмани + середньорядні Android)
- Опціональна інтеграція 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 – хороша стартова точка.





