Реалізація AR-сканування площин у мобільному застосунку
Ми часто стикаємося з ситуацією: клієнт хоче розмістити віртуальний диван у кімнаті, але застосунок показує «плаваючий» об'єкт без чіткої прив'язки до підлоги. Користувач розчарований, а розробник впирається в обмеження платформених SDK. Стабільне визначення площин — ключ до переконливого AR. Без нього будь-який AR-об'єкт сприймається як чужорідний елемент. Ми навчилися доводити plane detection до стану «стоїть як справжнє» за 5-8 днів.
Платформені API та їх реальні обмеження
ARKit (iOS). ARWorldTrackingConfiguration з planeDetection: [.horizontal, .vertical]. ARKit повертає ARPlaneAnchor з ARPlaneGeometry — mesh площини, який оновлюється в міру сканування. Проблема: на перших секундах ARKit повертає маленький прямокутник, який агресивно змінює розмір та орієнтацію. Якщо розмістити об'єкт одразу — він «стрибне» при наступному оновленні.
Рішення — мінімальний confidence threshold і debounce на оновлення. ARPlaneAnchor не має явного поля confidence, але розмір площини (extent) слугує непрямим показником зрілості: не показувати UI для розміщення, доки extent.x < 0.3 та extent.z < 0.3 метра.
ARCore (Android). Plane з TrackingState.TRACKING і PlaneType.HORIZONTAL_UPWARD_FACING / VERTICAL. ARCore додатково надає Plane.getSubsumedBy() — коли дві площини зливаються в одну. Це ламає логіку, якщо якорі були прив'язані до вихідних площин — потрібно переносити Anchor на subsuming plane.
Vertical planes. ARKit стабільно визначає вертикальні площини на текстурованих поверхнях (стіна з шпалерами — добре, монотонно біла стіна — погано). ARCore з vertical detection працює ще менш впевнено. Для продуктів, де критична навіска на стіну (картини, полиці), краще використовувати комбінацію plane detection + LiDAR (iPhone 12 Pro+) для добудови відсутньої геометрії.
Як LiDAR змінює правила гри?
На пристроях з LiDAR (iPhone 12 Pro, 13 Pro, 14 Pro, 15 Pro, iPad Pro) ARKit будує dense mesh оточення через ARMeshAnchor. Plane detection з LiDAR працює принципово інакше: площини виводяться з mesh, а не з візуального SLAM. Це дає:
- Детектування площини за 1-2 секунди замість 5-10
- Стабільні межі навіть на монотонних поверхнях
- Коректне визначення сходинок, пандусів, похилих площин
Для застосунків, де LiDAR-пристрої — основна ЦА (професійна зйомка, ремонт, будівництво), перемикання між ARWorldTrackingConfiguration та конфігурацією з sceneReconstruction: .mesh дає якісний стрибок.
Чому площина «стрибає» і як це виправити?
Основна причина — розміщення об'єкта до того, як площина стабілізувалася. Confidence threshold і debounce вирішують проблему на 80%. Перевірений підхід:
- Не показувати кнопку розміщення, доки розмір площини не перевищить 0.3 метра по кожній осі.
- При оновленні площини плавно переміщати якір з анімацією (наприклад,
SCNActionу SceneKit абоUIView.animateу RealityKit). - Використовувати
ARWorldTrackingConfiguration.isAutoFocusEnabledдля покращення якості кадру.
Детальний чек-лист стабільного розміщення
- Перевіряти `ARPlaneAnchor.extent.x > 0.3` та `extent.z > 0.3` - Ігнорувати оновлення площини протягом 0.5 секунд після першого детектування - На LiDAR-пристроях використовувати `ARMeshAnchor` для більш точної геометрії - Завжди обробляти `ARCamera.TrackingState` і блокувати UI при `LIMITED`Візуалізація прогресу сканування
Користувач не знає, що потрібно «поводити» камерою — потрібна чітка підказка. Типові патерни:
- Анімований сканувальний промінь з нижньої частини екрану
- Outline площини, який «росте» в міру виявлення
- Текстова інструкція з автосхованням після першого успішного detection
Для відмальовки меж площини в RealityKit — ModelEntity з wireframe матеріалом, прив'язаний до PlaneAnchor. У SceneKit — SCNNode з SCNGeometry з ARPlaneGeometry.boundaryVertices. У ARCore Scenekit/Filament — власний mesh з Plane.getPolygon().
Типові проблеми в production
Площина «ламається» при сильному русі камерою — tracking state переходить у LIMITED(.excessiveMotion). Потрібно блокувати розміщення об'єктів і показувати попередження, а не крашитися.
На темних поверхнях (темний ламінат, чорний килим) ARKit і ARCore втрачають features для візуального SLAM. Попередження через ARCamera.TrackingState.Reason.insufficientFeatures — обов'язково обробляти та повідомляти користувача.
Що входить у роботу
- Тестування на цільових пристроях з оцінкою стабільності
- Оптимізація під LiDAR (якщо підтримується)
- Реалізація multi-plane selection (можливість вибору площини дотиком)
- Збереження ARWorldMap для повторного використання сцени
- Документація з інтеграції та налаштування
- Гарантія стабільної роботи: ми даємо 30 днів безкоштовної підтримки після здачі
| Платформа | API | Особливості |
|---|---|---|
| iOS (ARKit) | ARPlaneAnchor, ARWorldTrackingConfiguration | Швидкий старт, але потрібен debounce |
| Android (ARCore) | Plane, getSubsumedBy() | Злиття площин, перенесення якорів |
| LiDAR-пристрої | ARMeshAnchor | Детектування за 1-2 сек, стабільність |
Порівняння методів візуалізації
| Інструмент | Візуалізація меж | Продуктивність | Гнучкість |
|---|---|---|---|
| RealityKit | ModelEntity з wireframe | Висока | Середня |
| SceneKit | SCNNode з boundaryVertices | Середня | Висока |
| ARCore + Filament | Mesh з getPolygon() | Середня | Висока |
Документація Apple ARKit: ARKit Plane Detection Документація Google ARCore: Plane Detection
Терміни орієнтовно
Реалізація базового plane detection з візуальною підказкою та розміщенням об'єкта — від 5 до 8 днів. Доробка під LiDAR, multi-plane selection, збереження ARWorldMap — ще 5-7 днів. Вартість розраховується індивідуально, залежно від складності. Отримайте консультацію — зв'яжіться з нами для оцінки вашого проекту.
Наша команда має 5+ років досвіду в AR-розробці та понад 20 успішних проектів. Замовте реалізацію під ключ і отримайте консультацію безкоштовно.







