Привет! Меня зовут Андрей Груненков, я iOS - разработчик в агентстве InstaDev. Делаем мобильные приложения, которые помогают бизнесу расти. В этой статье я расскажу о том, как разработать первое мобильное приложение для платформы Apple Vision Pro.

Для начала надо сказать пару слов о самой платформе. Apple Vision Pro это компьютер Apple, который предоставляет пользователю новый опыт пространственного взаимодействия с интерфейсом. По сути представляет из себя гарнитуру смешанной реальности (AR/VR).

Достаточно просто надеть устройство на голову, чтобы погрузиться в последние проекты или трёхмерный контент.

Гарнитура отслеживает движение  глаз пользователя, передает изображение с внешних камер на дисплеи перед глазами и показывает 3D-контент. При нажатии на одну кнопку можно погрузиться в виртуальный мир, в остальное время окна и приложения перемещаются в воздухе перед пользователем и дают возможность с ними взаимодействовать.

Apple Vision Pro помогает решать следующие задачи:

  • обзор пространственных фотографий;

  • просмотр фильмов, как на экране высокого разрешения;

  • просмотр игр в Apple Arcade;

  • возможность рабочих процессов с использованием нескольких виртуальных окон вместо мониторов, что является дополнительным удобством для программистов;

  • сёрфинг соцсетей;

  • общение по Facetime;

  • использование в качестве внешнего монитора для Mac.

Технические характеристики

Apple Vision Pro

Тип продукта

Шлем виртуальной/дополненной реальности

Дисплеи

Два 3D Micro-OLED-дисплея; суммарное разрешение – 23 Мп; плотность пикселей – 3386 ppi; адаптивная частота обновления – до 100 Гц; межзрачковое расстояние – 51-75 мм

Аппаратная платформа

Apple M2 (8 ядер: 4 × Avalanche + 4 × Blizzard; 10-ядерная графическая подсистема); сопроцессор обработки данных Apple R1

Память

256/512/1024 Гбайт

Сенсоры

Две основные камеры (стереоскопическая камера), шесть камер-трекеров, четыре камеры для отслеживания глаз, камера TrueDepth, сканер LiDAR, четыре гироскопа, датчик освещения, датчик мерцания, датчик распознавания пользователя Optic ID

Камера

Стереоскопическая камера; фокусное расстояние оптики 18 мм, светосила – f/2,0; разрешение сенсора – 6,5 Мп; съемка фото и видео

Звуковая система

Динамики с поддержкой персонального пространственного аудио; технология передачи звука с низкой задержкой при подключении AirPods Pro 2; шесть микрофонов

Форматы передачи звука

AAC, MP3, Apple Lossless, FLAC, Dolby Digital, Dolby Digital Plus, and Dolby Atmos

Операционная система

visionOS

Беспроводные модули

Wi‑Fi 6 (802.11ax) 

Bluetooth 5.3

Батарея

35,9 Вт·ч; подключается по кабелю через проприетарный порт

Вес

Гарнитура — 650 граммов, батарея — 350 граммов

Цена

От $3 500 в США; от 478 000 рублей в России

Процессор

В шлем смешанной реальности вшиты сразу два мощных процессора. Первый — М2, он уже показал себя в Mac и iPad последних поколений. Второй — VR-процессор R1, который собирает информацию со всех датчиков, микрофонов и камер, обрабатывает ее и выводит изображение на экран. Apple заявляет, что на этот процесс уходит не более 12 миллисекунд.

Память

Доступны шлемы со встроенной памятью на 256 или 512 гигабайт, а также на один терабайт. Оперативная память при этом составляет 16 гигабайт.

Изображение

За картинки и видео отвечают два Micro OLED дисплея с разрешением 23 мегапикселя. Они создают 3D-систему, обеспечивают плавность изображения, а также глубину и разнообразие цветов. Угол обзора в шлеме — 140 градусов.

Звук

В шлем встроены шесть микрофонов и сложная аудиосистема. Она сканирует помещение, в котором находится пользователь, и адаптирует звучание. Гарнитура дополненной реальности совместима с наушниками AirPods Pro 2.

Камеры

Всего в устройстве 13 камер, в том числе две основные камеры с высоким разрешением. Во внутренней части действуют еще четыре — для отслеживания движения глаз. Еще шесть камер ориентированы на окружающий мир. Они делают фото и видео, которые нужны для создания 3D-системы.

Сенсоры

Также в гарнитуру встроены различные сенсоры и датчики: например, датчик освещенности, датчик мерцания и другие.

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

Управление

Доступно управление гаджетом взглядом и жестами. Для активации экрана нужно дотронуться указательным пальцем до большого, то есть «щелкнуть» в воздухе. Также есть колесико Digital Crown и кнопки на корпусе. Можно вызвать виртуальную клавиатуру и печатать, нажимая на кнопки пальцами в воздухе.

Совместимость

Vision Pro подключается к MacBook, работая в качестве виртуального монитора. Также гарнитура совместима с мышкой и клавиатурой от Apple. Интерфейс знаком всем пользователям продукции бренда.

Зарядка

Устройство заряжается от съемного аккумулятора, который можно подключать с помощью кабеля. Сам аккумулятор компактный, легко помещается в карман. Заявленное время автономной работы гарнитуры — 2,5 часа.

Крепление

Гарнитура надевается на голову с помощью ремешков, причем можно выбрать один из двух вариантов, представленных производителем. Первый, более компактный и красивый, включает в себя один ремень Solo Knit Band с 3D-креплением. Второй — Dual Band, для более устойчивого крепления. Он снимает нагрузку с шеи.

Материалы

Сам шлем сделан из стекла и алюминия, вес устройства составляет порядка 650 граммов. Дизайн повторяет очертания человеческого лица, из-за чего выглядит эcтетичнее и более футуристично, чем его конкуренты. В боковых частях шлема расположен мягкий уплотнитель Light Seal, блокирующий свет из окружающего мира.

Перед покупкой Vision Pro нужно отсканировать лицо с помощью технологии Face ID на iPhone, чтобы производитель подобрал внутреннюю мягкую подкладку нужной формы и размера.

Далее я раскрою несколько терминов, понимание которых потребуется в дальнейшем.

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

Дополненная реальность - это среда, в которой настоящий мир дополняется цифровыми элементами, такими как 3D-объекты, картинки, текст, звук, анимация и прочие.

Размещать виртуальные объекты в пространстве не хаотично, а в определённых местах можно разными способами, вот 3 из них.

 1. Привязка к маркеру

Объекты накладывают с помощью специальных маркеров, например QR-кодов или картинок. При наведении камеры на такой маркер на его месте пользователь видит на экране виртуальный объект. 

2. Привязка к плоскости

Объект в дополненной реальности появляется в пространстве, привязанный к определённой точке, выбранной устройством в результате сканирования. Распознаются как горизонтальные, так и вертикальные плоскости.

3. Привязка к геолокации

Виртуальные элементы размещают в пространстве на основе местоположения реальных объектов и времени взаимодействия пользователя с дополненной реальностью. Для этого используются данные с камеры, датчиков устройства, GPS и прочих источников и систем. 

Разберем создание первого приложения под VisionOS.

Для разработки приложений под visionOS используется фреймворки ARKit и RealityKit. 

Когда мы создаем новый проект в Xcode, нам открывается новый помощник проекта.

Он упорядочивает шаблоны проектов по платформам и типам проектов.

Шаблон проекта приложения доступен в разделе «Приложение» на вкладке «Платформа».

Новый помощник проекта представляет нам несколько опций, две из которых являются новыми для этой платформы.

Давайте подробнее рассмотрим каждую из этих опций.

Initial Scene

Первая новая опция Initial Scene позволяет нам указать тип начальной сцены, которая автоматически включается в приложение. Новый помощник проекта всегда создает отправную точку с одной сцены выбранного вами здесь типа. Как разработчик, вы можете добавить дополнительные сцены позже.

Они могут быть того же типа, что и исходная сцена, или  принадлежать к другому типу сцены.

Шаблон предлагает два типа сцены: Window и Volume.

Давайте посмотрим на различия между ними.

Windows предназначена для представления содержимого, которое в основном является двухмерным. Их плоские размеры можно изменить, но их глубина фиксирована.

Windows обычно отображается рядом с другими запущенными приложениями.

Volume предназначен в первую очередь для представления 3D-контента.

Их размеры во всех трех измерениях контролируются самим приложением, но не могут быть изменены пользователем, использующим приложение.

 Как и окна, объемы обычно отображаются рядом с другими запущенными приложениями.

Immersive Space

Вторая новая опция, Immersive Space, дает вам возможность добавить в ваше приложение отправную точку для иммерсивного контента.

SwiftUI предлагает три различных стиля для вашей сцены: Mixed, Progressive и Full.

 Mixed позволяет вашему приложению размещать неограниченное виртуальное содержимое в полном пространстве, сохраняя при этом связь людей с окружением посредством сквозной связи.

Progressive открывает портал, предлагающий более захватывающий опыт, который не полностью удаляет пользователей из их окружения. Когда портал открывается, пользователи получают обзор вашего иммерсивного контента примерно на 180 градусов и могут использовать Digital Crown для регулировки размера портала.

Full полностью скрывает проход и окружает пользователей средой вашего приложения, перенося их в новое место.

По умолчанию в ваше приложение добавляется тип Mixed.

Apple рекомендует делать приложения всегда запускающимися в окне и обеспечивать четкие элементы управления входом и выходом, чтобы люди могли решить, когда им лучше погрузиться в ваш контент.

Для создания UI и иммерсионного контента используется SwiftUI.

Создаем проект и видим, что Xcode сгенерировал 3 структуры: myFirstApp, ContentView и ImmersiveView.

myFirstApp описывает основную сцену нашего приложения:

import SwiftUI
@main
struct myFirstApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        ImmersiveSpace(id: "ImmersiveSpace") {
            ImmersiveView()
        }
    }
}

ContentView - контент основного окна нашего приложения

import SwiftUI
import RealityKit
import RealityKitContent
struct ContentView: View {
    @State private var showImmersiveSpace = false
    @State private var immersiveSpaceIsShown = false
    @Environment(\.openImmersiveSpace) var openImmersiveSpace
    @Environment(\.dismissImmersiveSpace) var dismissImmersiveSpace
    var body: some View {
        VStack {
            Model3D(named: "Scene", bundle: realityKitContentBundle)
                .padding(.bottom, 50)
            Text("Hello, world!")
            Toggle("Show ImmersiveSpace", isOn: $showImmersiveSpace)
                .font(.title)
                .frame(width: 360)
                .padding(24)
                .glassBackgroundEffect()
        }
        .padding()
        .onChange(of: showImmersiveSpace) { _, newValue in
            Task {
                if newValue {
                    switch await openImmersiveSpace(id: "ImmersiveSpace") {
                    case .opened:
                        immersiveSpaceIsShown = true
                    case .error, .userCancelled:
                        fallthrough
                    @unknown default:
                        immersiveSpaceIsShown = false
                        showImmersiveSpace = false
                    }
                } else if immersiveSpaceIsShown {
                    await dismissImmersiveSpace()
                    immersiveSpaceIsShown = false
                }
            }
        }
    }
}

ImmersiveView - иммерсивный контент

import SwiftUI
import RealityKit
import RealityKitContent
struct ImmersiveView: View {
    var body: some View {
        RealityView { content in
            // Add the initial RealityKit content
            if let scene = try? await Entity(named: "Immersive", in: realityKitContentBundle) {
                content.add(scene)
            }
        }
    }
}

Только что созданное приложение имеет основное окно с переключателем, добавляющим/удаляющим иммерсивное пространство Mixed типа.

Добавим в проект возможность включать иммерсивные пространства разных типов. Для каждого типа пространства создадим свое View и добавим их в основную структуру приложения.

import SwiftUI
@main
struct myFirstApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        ImmersiveSpace(id: "MixedImmersiveSpace") {
            MixedImmersiveView()
        }
        .immersionStyle(selection: .constant(.mixed), in: .mixed)
        
        ImmersiveSpace(id: "FullImmersiveSpace") {
            FullImmersiveView()
        }
        .immersionStyle(selection: .constant(.full), in: .full)
        
        ImmersiveSpace(id: "ProgressiveImmersiveSpace") {
            ProgressiveImmersiveView()
        }
        .immersionStyle(selection: .constant(.progressive), in: .progressive)
    }
}

В интерфейс основного окна добавим переключатели для всех типов пространств

import SwiftUI
import RealityKit
import RealityKitContent
struct ContentView: View {
    @State private var showMixedImmersiveSpace = false
    @State private var showProgressiveImmersiveSpace = false
    @State private var showFullImmersiveSpace = false
    
    @State private var immersiveSpaceIsShown = false
    @Environment(\.openImmersiveSpace) var openImmersiveSpace
    @Environment(\.dismissImmersiveSpace) var dismissImmersiveSpace
    var body: some View {
        VStack {
            Model3D(named: "Scene", bundle: realityKitContentBundle)
                .padding(.bottom, 50)
            Toggle("Show Mixed ImmersiveSpace", isOn: $showMixedImmersiveSpace)
                .disabled(showProgressiveImmersiveSpace || showFullImmersiveSpace)
                .font(.title)
                .frame(width: 360)
                .padding(24)
                .glassBackgroundEffect()
            
            Toggle("Show Progressive ImmersiveSpace", isOn: $showProgressiveImmersiveSpace)
                .disabled(showMixedImmersiveSpace || showFullImmersiveSpace)
                .font(.title)
                .frame(width: 360)
                .padding(24)
                .glassBackgroundEffect()
            
            Toggle("Show Full ImmersiveSpace", isOn: $showFullImmersiveSpace)
                .disabled(showMixedImmersiveSpace || showProgressiveImmersiveSpace)
                .font(.title)
                .frame(width: 360)
                .padding(24)
                .glassBackgroundEffect()
        }
        .padding()
        .onChange(of: showMixedImmersiveSpace) { _, newValue in
            Task {
                await handleImmersiveSpace(id: "MixedImmersiveSpace", isShown: newValue)
            }
        }
        .onChange(of: showFullImmersiveSpace) { _, newValue in
            Task {
                await handleImmersiveSpace(id: "FullImmersiveSpace", isShown: newValue)
            }
        }
        .onChange(of: showProgressiveImmersiveSpace) { _, newValue in
            Task {
                await handleImmersiveSpace(id: "ProgressiveImmersiveSpace", isShown: newValue)
            }
        }
    }
    
    private func handleImmersiveSpace(id: String, isShown: Bool) async {
        if isShown {
            switch await openImmersiveSpace(id: id) {
            case .opened:
                immersiveSpaceIsShown = true
            case .error, .userCancelled:
                fallthrough
            @unknown default:
                immersiveSpaceIsShown = false
                showProgressiveImmersiveSpace = false
            }
        } else if immersiveSpaceIsShown {
            await dismissImmersiveSpace()
            immersiveSpaceIsShown = false
        }
    }
}

Теперь запустим приложение и посмотрим, как оно будет себя вести при переключении пространств.

После включения Full ImmersiveSpace появится предупреждение о погружении в виртуальные пространство, и необходимости принять меры предосторожности, и после тапа на ОК произойдет переключение в полное иммерсивное пространство. Все окружение исчезает и мы видим только виртуальный контент.

Переключимся на Progressive ImmersiveSpace. Как и в прошлом случае, появится предупреждение. В этот раз мы увидим виртуальные пространство внутри некого портала.

Переключимся на тип Mixed, который установлен по умолчанию и видим привычное окружение и виртуальный контент.

Далее попробуем добавить контент в смешанное иммерсивное пространство методом привязки к плоскости, привяжем сферу из встроенного дефолтного пакета контена к поверхности стола. 

Для этого в RealityKit существует класс AnchorEntity:

import SwiftUI
import RealityKit
import RealityKitContent
struct MixedImmersiveView: View {
    var body: some View {
        RealityView { content in
            if let scene = try? await Entity(named: "Scene", in: realityKitContentBundle) {
                let horizontalAnchor = AnchorEntity(.plane(.horizontal, classification: .table, minimumBounds: SIMD2<Float>(0.5, 0.5)))
                horizontalAnchor.addChild(scene)
                content.add(horizontalAnchor)
            }
        }
    }
}

Запустим проект и включим Mixed ImmersiveSpace. После того как Apple Vision Pro отсканируют поверхность стола, на нем появится дополненная сфера:

Таким образом, RealityKit предоставляет разработчикам довольно удобные инструменты для разработки приложений дополненной реальности и добавления в них иммерсивного контента.

Резюмирую

Apple Vision Pro перспективная VR/AR гарнитура, в которой безусловно присутствуют инновационные технологии.  Однако устройство требует доработок.

Гарнитура может использоваться разработчиками для создания практически неограниченного рабочего пространства из множества окон, которое может заменить несколько мониторов.

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

Плюсы:

  • широкий спектр решаемых задач;

  • новый пользовательский опыт;

  • возможность создать бесконечное рабочее поле;

  • высокая вычислительная мощность дает новый уровень мобильности;

  • удобный SDK для разработки,  позволяющий быстро создавать приложения.

Минусы:

  • большой вес;

  • новые технологии еще недостаточно эргономичны. Управление взглядом приводит к быстрому утомлению глазных мышц;

  • не всех пользователей удовлетворяет качество картинки;

  • высокая стоимость;

  • в данный момент не доступно для российского региона.

Комментарии (0)