Разработка механик взаимодействия с дополненной реальностью (AR Foundation)
AR Foundation — это абстракция поверх ARKit (iOS) и ARCore (Android), которая позволяет писать один код под обе платформы. Но абстракция неполная: под ней живёт разная физика, разное качество плоскостного трекинга, разная скорость обновления depth map. Это означает, что механики взаимодействия нужно проектировать с учётом обеих платформ, и тестировать на реальных устройствах — не в редакторе.
Placement: размещение объектов в реальном пространстве
Базовая механика любого AR-приложения — разместить виртуальный объект на реальной поверхности. AR Foundation делает это через Raycast против AR Planes: ARRaycastManager.Raycast() бросает луч из точки касания экрана, возвращает список ARRaycastHit с позицией и нормалью плоскости.
Стандартная ошибка: вызывать Raycast каждый кадр в Update без debounce. Это работает, но на сложных сценах ARCore тратит 2–4 мс на raycast — это съедает бюджет. Правильно: raycast только при изменении позиции пальца, с минимальным threshold движения 5–10 пикселей.
Другая проблема — плоскость ещё не обнаружена. ARCore и ARKit детектируют горизонтальные плоскости за 2–5 секунд на хорошей текстурированной поверхности. На однотонном белом столе — никогда. Нужен feedback UI: визуальный индикатор поиска плоскостей, инструкция «подвигайте камерой над поверхностью».
ARAnchor: почему просто Transform.position недостаточно
Если поставить объект в AR и просто запомнить его worldPosition — при перемещении с устройством объект «плывёт» относительно реального мира. ARKit и ARCore периодически пересчитывают мировые координаты при улучшении трекинга. Объект без якоря сдвигается.
ARAnchor — это точка, которую AR система обязуется отслеживать и корректировать автоматически. Объект должен быть child ARAnchor'а, не просто помещён в мировые координаты.
В AR Foundation: ARAnchorManager.TryAddAnchorAsync(pose) возвращает ARAnchor, к которому крепится контент. При переоткрытии сцены (Persistent AR) — ARCore Cloud Anchors или ARKit WorldMap для сохранения якорей между сессиями.
Occlusion: реальный мир закрывает виртуальный объект
Без occlusion виртуальный объект рендерится поверх всего: ваза на столе отображается сквозь вашу руку. Это немедленно разрушает иллюзию.
AROcclusionManager в AR Foundation предоставляет depth texture от сенсора (LiDAR на iPhone Pro, алгоритмическая оценка глубины через камеру на Android). В URP шейдер должен проверять depth texture перед записью фрагмента — это Environment Depth Occlusion.
Настройка: AROcclusionManager.environmentDepthMode = EnvironmentDepthMode.Best (максимальное качество), occlusionPreferenceMode = OcclusionPreferenceMode.PreferEnvironmentOcclusion. На Android без LiDAR глубина оценочная — occlusion работает грубо, с артефактами на краях. На iPhone Pro с LiDAR — точно.
Без кастомного шейдера стандартный URP Lit не использует depth texture AR. Нужен либо ShaderGraph с AROcclusion нодой из AR Foundation Shader Framework, либо кастомный HLSL с ручным depth comparison.
Interaction: тап, drag, масштаб
В AR физических контроллеров нет — взаимодействие через тачскрин. Для объектов в AR стандартный набор:
Tap to select: ARRaycastManager + Physics.Raycast против collider объекта. При попадании — выделение через material change или outline.
Drag (translate): при перемещении пальца — новый AR Raycast возвращает новую позицию плоскости, объект Lerp-ится к ней. Без Lerp объект прыгает. speed = 15f в MoveTowards даёт плавное следование без залипания.
Pinch to scale: Touch[0] и Touch[1] — два пальца. Текущее расстояние между ними vs. предыдущее = scale delta. transform.localScale *= scaleDelta с зажатием в Vector3.one * minScale и maxScale.
Rotation: один палец, drag по горизонтали = rotation вокруг world-up axis. Два пальца, twist = rotation. Для AR рекомендуется ограничивать rotation только вокруг Y-axis — вращение по X или Z ломает ощущение «объект стоит на поверхности».
Сроки: базовый placement + interaction (tap/drag/scale) — 3–5 рабочих дней; full AR experience с Anchors, Occlusion, Persistent Cloud Anchors — 2–4 недели. Стоимость рассчитывается индивидуально после анализа требований.





