ARKit для Swift: Полное руководство по дополненной реальности
1. Что это и зачем нужна
ARKit — это фреймворк дополненной реальности (AR), разработанный компанией Apple для платформ iOS и iPadOS. Он позволяет разработчикам создавать захватывающие AR-приложения, которые накладывают виртуальные 3D-объекты, анимации и информацию на реальный мир, снятый камерой устройства. ARKit использует технологии компьютерного зрения, обработки данных с датчиков (акселерометр, гироскоп, камера) и машинного обучения для точного отслеживания положения устройства в пространстве, обнаружения плоскостей (столы, пол, стены) и распознавания изображений и объектов.
Зачем нужен ARKit? Он открывает безграничные возможности для самых разных сфер: от игр (Pokémon GO) и образования (интерактивные учебники) до розничной торговли (примерка мебели в IKEA Place) и промышленности (визуализация сложных механизмов). Вместо того чтобы писать сложные алгоритмы компьютерного зрения с нуля, разработчик получает готовый, оптимизированный и мощный инструмент, который берет на себя всю "тяжелую работу" по анализу видеопотока и отслеживанию.
В этой статье мы подробно разберем, как начать работу с ARKit на языке Swift, рассмотрим его основные классы и методы, а также напишем полноценный пример приложения. Вы узнаете, как быстро добавить AR-функциональность в ваш проект и избежать типичных ошибок.
2. Установка
ARKit — это не сторонняя библиотека, а встроенный фреймворк Apple. Его не нужно устанавливать через менеджеры пакетов (CocoaPods, Swift Package Manager) или pip. Для его использования достаточно импортировать его в ваш Xcode проект.
Важное замечание: ARKit работает только на устройствах с процессором A9 и выше (iPhone 6s и новее, iPad 2017 и новее) и требует iOS 11.0 или новее. Для симулятора Xcode поддержка ARKit ограничена (не работает камера), поэтому для полноценной разработки и тестирования необходимо физическое устройство.
Шаги для начала работы:
- Откройте Xcode и создайте новый проект (File → New → Project).
- Выберите шаблон "Augmented Reality App". Xcode автоматически настроит проект с использованием SceneKit (или RealityKit) и ARKit.
- Если вы добавляете ARKit в существующий проект, просто импортируйте фреймворк в нужный файл.
Команда для импорта (в коде):
import ARKit
Больше никаких команд установки не требуется. Если вы используете RealityKit (более современный фреймворк для AR), импортируйте его:
import RealityKit
3. Быстрый старт — минимальный рабочий пример
Давайте создадим минимальное AR-приложение, которое отобразит простой 3D-куб на обнаруженной горизонтальной плоскости.
1. Настройка ViewController:
Убедитесь, что ваш ViewController наследуется от ARSCNViewDelegate (для SceneKit) или ARViewDelegate (для RealityKit). В этом примере мы используем SceneKit, так как он более прост для понимания основ.
import UIKit
import ARKit
class ViewController: UIViewController, ARSCNViewDelegate {
@IBOutlet var sceneView: ARSCNView!
override func viewDidLoad() {
super.viewDidLoad()
sceneView.delegate = self
sceneView.showsStatistics = true // Показывает FPS и другую статистику
sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints] // Показывает точки, которые видит камера
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = [.horizontal] // Включаем обнаружение горизонтальных плоскостей
sceneView.session.run(configuration)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
sceneView.session.pause() // Останавливаем сессию, когда приложение уходит на фон
}
}
2. Добавление объекта при обнаружении плоскости:
Реализуем метод делегата renderer(_:didAdd:for:), который вызывается, когда ARKit находит новую плоскость.
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
// 1. Проверяем, что это плоскость
guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
// 2. Создаем геометрию плоскости (визуализация найденной поверхности)
let plane = SCNPlane(width: CGFloat(planeAnchor.extent.x), height: CGFloat(planeAnchor.extent.z))
let planeNode = SCNNode(geometry: plane)
planeNode.position = SCNVector3(planeAnchor.center.x, 0, planeAnchor.center.z)
planeNode.transform = SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0) // Поворачиваем плоскость
// 3. Добавляем куб на эту плоскость
let box = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
let boxNode = SCNNode(geometry: box)
boxNode.position = SCNVector3(0, 0.05, 0) // Поднимаем куб на половину его высоты
// 4. Добавляем узлы в сцену
planeNode.addChildNode(boxNode)
node.addChildNode(planeNode)
}
Этот минимальный пример показывает, как запустить AR-сессию, обнаружить плоскость и разместить на ней 3D-объект. Запустите приложение на реальном устройстве и наведите камеру на стол или пол — вы увидите куб.
4. Основные методы/функции/классы
Рассмотрим 8 ключевых классов и методов ARKit, которые вам понадобятся в 90% проектов.
4.1. ARSession
Сигнатура: class ARSession
Что делает: Это центральный объект, управляющий всем процессом AR. Он принимает конфигурацию, запускает и останавливает обработку данных с камеры и датчиков, а также управляет всеми обнаруженными якорями (ARAnchor).
Пример:
let session = ARSession()
let configuration = ARWorldTrackingConfiguration()
session.run(configuration)
// ... через какое-то время
session.pause()
4.2. ARWorldTrackingConfiguration
Сигнатура: class ARWorldTrackingConfiguration
Что делает: Основная конфигурация для отслеживания мира. Она использует визуально-инерциальную одометрию (VIO) для точного отслеживания положения устройства в 6 степенях свободы (6 DOF: перемещение и поворот). Позволяет настроить обнаружение плоскостей, распознавание изображений и объектов.
Пример:
let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = [.horizontal, .vertical] // Ищем и горизонтальные, и вертикальные плоскости
configuration.environmentTexturing = .automatic // Автоматическое текстурирование окружения для реалистичного освещения
sceneView.session.run(configuration)
4.3. ARAnchor и ARPlaneAnchor
Сигнатура: class ARAnchor / class ARPlaneAnchor: ARAnchor
Что делает: ARAnchor — это базовая точка в пространстве, к которой можно "привязать" виртуальный объект. ARPlaneAnchor — это подкласс, представляющий обнаруженную плоскость (пол, стол, стена). Он содержит информацию о положении, размере (extent) и центре (center) плоскости.
Пример:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
if let planeAnchor = anchor as? ARPlaneAnchor {
print("Обнаружена плоскость шириной \(planeAnchor.extent.x) и высотой \(planeAnchor.extent.z)")
// Создаем визуальный узел для плоскости
}
}
4.4. ARSCNViewDelegate
Сигнатура: protocol ARSCNViewDelegate
Что делает: Протокол делегата для ARSCNView. Предоставляет методы для обработки событий жизненного цикла AR-сессии и управления узлами SceneKit, которые соответствуют якорям. Ключевые методы: renderer(_:didAdd:for:), renderer(_:didUpdate:for:), renderer(_:didRemove:for:).
Пример:
class ViewController: UIViewController, ARSCNViewDelegate {
// ... реализация методов делегата
func session(_ session: ARSession, didFailWithError error: Error) {
print("Ошибка сессии: \(error.localizedDescription)")
}
func sessionWasInterrupted(_ session: ARSession) {
print("Сессия прервана")
}
func sessionInterruptionEnded(_ session: ARSession) {
print("Сессия возобновлена")
}
}
4.5. SCNScene и SCNNode
Сигнатура: class SCNScene / class SCNNode
Что делает: SCNScene — это корневой контейнер для всей 3D-сцены. SCNNode — это узел в графе сцены. Каждый узел может содержать геометрию (SCNGeometry), источники света, камеры и другие узлы (дочерние). Именно через узлы вы размещаете и перемещаете объекты в AR-пространстве.
Пример:
// Создаем сферу
let sphere = SCNSphere(radius: 0.05)
let sphereNode = SCNNode(geometry: sphere)
sphereNode.position = SCNVector3(0, 0.1, -0.5) // 50 см перед камерой, 10 см вверх
// Добавляем в корневую сцену
sceneView.scene.rootNode.addChildNode(sphereNode)
4.6. ARHitTestResult (Устарел в iOS 14, используйте raycast)
Сигнатура: class ARHitTestResult / func raycastQuery(from:allowing:alignment:)
Что делает: Позволяет определить, на какой объект реального мира (или существующий якорь) указывает точка на экране. Это основа для взаимодействия пользователя с AR-миром (например, касание экрана для размещения объекта). Начиная с iOS 14, Apple рекомендует использовать ARRaycastQuery вместо hit-test.
Пример (с использованием raycast):
@IBAction func handleTap(_ gesture: UITapGestureRecognizer) {
let tapLocation = gesture.location(in: sceneView)
guard let query = sceneView.raycastQuery(from: tapLocation, allowing: .existingPlaneGeometry, alignment: .horizontal) else { return }
let results = sceneView.session.raycast(query)
if let firstResult = results.first {
let transform = firstResult.worldTransform
let position = SCNVector3(transform.columns.3.x, transform.columns.3.y, transform.columns.3.z)
// Размещаем объект в этой позиции
let boxNode = SCNNode(geometry: SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0))
boxNode.position = position
sceneView.scene.rootNode.addChildNode(boxNode)
}
}
4.7. ARImageAnchor и ARReferenceImage
Сигнатура: class ARImageAnchor: ARAnchor / class ARReferenceImage
Что делает: Позволяет распознавать заранее заданные 2D-изображения (логотипы, постеры, картины) в реальном мире. Когда изображение распознано, создается ARImageAnchor, к которому можно привязать виртуальный контент (например, анимацию поверх журнала).
Пример:
// В конфигурации
guard let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else { return }
configuration.detectionImages = referenceImages
// В делегате
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let imageAnchor = anchor as? ARImageAnchor else { return }
print("Обнаружено изображение: \(imageAnchor.referenceImage.name ?? "unknown")")
// Добавляем 3D-текст поверх изображения
let textNode = SCNNode(geometry: SCNText(string: "Hello AR!", extrusionDepth: 0.1))
textNode.position = SCNVector3(0, 0.1, 0)
node.addChildNode(textNode)
}
4.8. ARSCNDebugOptions
Сигнатура: struct ARSCNDebugOptions
Что делает: Набор опций для визуальной отладки AR-сессии. Позволяет отображать на экране "фиче-поинты" (ключевые точки, которые видит камера), мировые оси координат, сетки обнаруженных плоскостей и другую отладочную информацию. Незаменимо при разработке для понимания того, что "видит" ARKit.
Пример:
sceneView.debugOptions = [
.showFeaturePoints, // Показывает желтые точки
.showWorldOrigin, // Показывает оси X, Y, Z в начале координат
.showAnchorOrigins, // Показывает оси для каждого якоря
.showAnchorGeometry // Показывает геометрию якорей (например, плоскости)
]