Миссия выполнима: как мы создали приложение для Apple Vision Pro за 8 дней

Всем привет! На связи Саша Сырков из 2ГИС, и это рассказ, как чуть больше недели мы разрабатывали приложение на Vision OS, разбирались в особенностях Reality Composer Pro, ловили всевозможные текстурные баги, а в итоге всё же получили заветный апрув от Apple за 17 часов до официального открытия продаж VR-гарнитуры.

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

От мысли до… 2GIS Immersive

Идея реализовать VR родилась в июне 2023, когда Apple анонсировала выход Vision OS. Vision Pro выглядел как устройство, на котором можно красиво показать наши карты с детальными объектами.

Рабочей гарнитуры у нас, разумеется, не было, но это не помеха разработке. У Apple есть симулятор, который почти полностью повторяет функционал реального устройства. Симулятор идёт вместе с новой версией Xсode 15 и позволяет эмулировать жесты, окружение и систему.

Обсудили с командой, что можем попробовать запустить 2ГИС на новой платформе. В январе 2024-го мы адаптировали приложение под Vision Pro, которое запускалось в режиме совместимости с iPad-версией в виде плоского окна.

b39f56e668b8a92c044d54a2b442831f.png

Такая реализация достаточно быстрая, но совсем не раскрывала главное преимущество платформы — 3D-сценарии — и не давала почувствовать истинный кайф от работы с Vision Pro. Однако переносить всё приложение 2ГИС в 3D было бы очень сложно.

В середине января в социальных сетях начинают появляться посты в духе «ааа, я получу свой вижн про 2 февраля», а у меня — мысли, что не обязательно повторять все продуктовые сценарии, например, поиск проезда или выбор компаний: с этим справится и плоское приложение. У нас были готовые 3D-модели зданий, а у Vision Pro был встроенный редактор, поэтому решили сосредоточиться на возможности со всех сторон рассмотреть эти красивые детальные модели прямо в комнате пользователя. Так родился отдельный продукт 2GIS Immersive. 

9 рабочих дней до релиза Apple Vision Pro

В понедельник 22 января у нас собралась небольшая фича-тим: менеджер (я), VR-разработчик, 3D-моделлер, iOS-разработчик, дизайнер интерфейса и дизайнер иконки.

Уже вместе мы добрейнштормили вариант простого, но в тоже время зрелищного приложения — небольшой энциклопедии с достопримечательностями. Первый прототип собрали уже вечером в этот же день.

Особенности разработки на VisionOS

После набросков первоначального дизайна началась разработка и вёрстка на Swift и фреймворке SwiftUI.

Главное преимущество использования SwiftUI — единая система компонентов для всех устройств Apple. Если разрабатывать приложение для iPhone или iPad, а затем захочется его перенести на Apple Vision Pro, то можно переиспользовать свой старый код, немного дополнив его визуальными улучшениями.

К примеру, нужно добавить такие компоненты как .hoverEffect, чтобы при наведении взгляда на кнопку или элемент появлялся визуальный отклик. Также появились новые материалы для фона, создающие эффект замутнённого стекла с помощью параметра .glassBackgroundEffect ().

Более подробно о новых SwiftUI-элементах Apple рассказывает в своих обучающих роликах, которые можно найти на их официальном сайте. Например, как строится дизайн для Spatial Computers или как перенести своё приложение на Vision Pro.

Но самым главным отличием в разработке для Vision Pro от обычных приложений стало использование трёхмерных сцен и объектов прямо в SwiftUI благодаря компоненту RealityView. Он позволяет использовать данные сцен, созданные с использованием нового инструмента Reality Composer Pro. С его помощью можно компоновать модели, создавать сцены, делать новые материалы, музыку, шейдеры и собственные компоненты.

8c386b16956d0c922fa94b890105f5f0.png

Reality Composer Pro визуально вдохновлён игровым движком Unity, который также поддерживает Vision Pro с момента его релиза. Но в отличие от нативного решения, которым воспользовались мы, Unity Technologies требует платную подписку Unity Pro в размере 2000 долларов в год, чтобы использовать движок для шлема.

Редактор поддерживает модели формата usdz/usdc, поэтому перед использованием их необходимо было экспортировать в него. Для этой задачи мы использовали Blender. Хотя существует также приложение для MacOS под названием Reality Converter, из-за особенностей оригинального формата модели проще было обработать в Blender. В Reality Composer уже происходило добавление материалов и текстур.

b6a7735b98031b10d1d99cd8e26d7eda.png

Наши модели были сделаны конкретно под движок 2ГИС, и при использовании для Vision Pro появлялись баги. У моделей то терялись текстуры, то группы сглаживания летели, то текстура ложилась на геометрию некорректно, то ещё что-нибудь ломалось, рябило или порождало артефакты. Приходилось по ходу вносить технические и косметические правки.

Есть также ограничение в 256 мегабайт на размер модели, которые не должны превышать размер кэша, а также в идеальном варианте на сцене не должны быть модели с миллионами вершин. Это мы узнали на практике, когда начали экспериментировать с большими моделями.

e830c0a5ee7a8531b603aa32dd8ce22a.png

Обычная анимация появления объекта из пустоты нам казалась скучной, поэтому используя функционал Reality Composer Pro и встроенный редактор шейдеров Shader Graph, сделали собственный эффект появления со свечением.

e55551c2774995764234675d6fd9b71c.gif

Создание шейдеров ничем не отличается от тех, что делаются в Unity или Unreal Engine. Единственно, что было неудобно — отсутствие превью на каждом из этапов создании, весь шейдер целиком можно увидеть только в редакторе Apple. Из-за этого приходилось создавать вслепую. После этого в инспекторе добавляются все нужные текстуры и настраиваются параметры.

Финальный шейдер выглядел так ↓

d1b541e4bff1e65687179f33b0714118.png

Возникает вопрос: как обратиться к шейдеру для изменения параметра Dissolve из Swift в Xcode? В этом случае нам на помощь приходит подход Entity-Component-System (ECS), который позволяет обращаться к созданным компонентам и просить их изменить параметр. Именно с использованием ECS-системы и собственного компонента на Swift мы создали анимацию появления и исчезания здания.

4c38152ac8d2423f2f0ea70856d1e6f5.png

Как только логика была написана, осталось только наполнить приложение нужными моделями зданий и описаниями. Все остальные элементы добавлены в Reality Composer Pro.

Добавить свою 3D-модель в интерфейс достаточно просто, используя ранее упомянутый элемент RealityView:

Swift
RealityView { content in
                if let scene = try? await Entity(named: modelName, in: realityKitContentBundle) {
                    content.add(scene)
                }
            }

А для старта анимации мы используем модификатор .onAppear:

Swift
.onAppear {
    startDissolveAnimation(
        startPosition: dissolveStartPosition, 
        endPosition: dissolveEndPosition, 
        animationDuration: TimeInterval(duration))
}

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

Мы также хотели дать возможность пользователю помещать виртуальные объекты на реальные поверхности. Для этой цели Apple внедрила новую парадигму объектов, называемую Immersive Spaces. Это то же интерфейсное окно, реализованное с помощью SwiftUI, но с добавлением трёхмерной модели. Особенность этой концепции в отсутствии привязки к существующим окнам, а это значит, что их позиция не изменится при центрировании.

00d2563988785b5043a4be53ea4b753c.png

По итогу наш базовый скрипт состоит из двух сущностей с набором окон и отдельным трёхмерным объектом, который можно двигать.

@main
struct doublegisAVPApp: App {
    @State private var model = ViewModel()
    @State private var mixedImmersionStyle: ImmersionStyle = .mixed
    @State private var IsRestricted = false
    
    var body: some Scene {
        WindowGroup("2GIS Immersion", id: "modules") {
            Modules().environment(model)
        }
        .windowStyle(.plain)
        
        ImmersiveSpace() {
            ImmersiveView(modelName: model.currentBuilding).environment(model)
        }
        .immersiveStyle(selection: $mixedImmersionStyle, in: .mixed)
    }
    }

Ещё одна особенность: в VisionOS-окружении требуется, чтобы иконка состояла из нескольких слоёв (два или три): фона и передней часть иконки.

00e3a7a39088550ddadaace271550a3c.png

Именно это позволяет верхнему слою иконки всплывать при фокусировке взгляда.

625447808c359ee0c52df6c62b798aa1.gif

Два дня до релиза

Одной из последних моделей мы делали Кремль — его обязательно хотели добавить в приложении вместе со всей Красной площадью. И вот 31 января в 23:00 у нас был готов релиз-кандидат билд, финально запускаем его, а в модели Кремля — дыра в полу. На предыдущих итерациях её не было, баг серьёзный, а сроки поджимали. Обычно проверка занимает целый день, и первые версии часто отклоняются Apple. У нас не было времени что-то менять, поэтому отправили на ревью версию 1.0 без Кремля.

Кстати, отдельный квест был с публикацией приложения в App Store, который требует 4К-скриншоты с разрешением 3840×2160 пикселей. Как уже упоминал, реального устройства Vision Pro у нас на руках не было, так как его продажи еще не начались, а эмулятор Vision OS даже на полноценном 4К-экране делал скриншоты с максимальным разрешением 2732×2048, что было заметно меньше нужного (мы проверяли, специально нашли 4К-монитор).

1e3448fdc9cee32fbc888f3f8a6cc7f9.png

Apple также оставляет возможность собрать в графическом редакторе виртуальные скриншоты своего приложения, но нам хотелось запечатлеть близкий к реальному опыт использования приложения, и мы нашли выход. С помощью современных AI Upscaler«ов можно легко превратить скриншоты более низкого разрешения в 4К, и выглядят они неотличимо от реального 4К: тот момент, когда современные технологии классно помогают в практических задачах!

Один день до релиза

Утром 1 февраля до релиза оставалось менее 24 часов, а приложение до сих пор не было одобрено. Пока ждали, разобрались с «кремлевской» дырой в полу и создали версию 1.1. И уже вечером, в момент самого отчаяния, нам приходит уведомление — приложение одобрено. За 17 часов до релиза!

Слева — плашка о том, что приложение прошло ревью и находится в ожидании релиза. Справа — счётчик до релиза очков Vision Pro в момент одобрения

Слева — плашка о том, что приложение прошло ревью и находится в ожидании релиза. Справа — счётчик до релиза очков Vision Pro в момент одобрения

В эту же ночь мы отправили на ревью новую версию, и опять происходит чудо: её одобрили за три часа до релиза!

А что в итоге

За 8 дней мы создали простое приложение, показав главные фишки технологий Vision Pro и RealityKit. Даже в большой и зрелой компании можно идти на эксперименты, сделать быстро и получить крутой результат. Ведь вся авантюра была не зря — мы попали в топ-600 первых VisionOS-приложений в мире и стали первыми в России.

Команда Apple прислала нам персональную благодарность за то, что приложение 2ГИС было в числе первых, кто поддержал Vision Pro.

ad9f03639f9f7affe4c76cfa4e84c24a.png

2GIS Immersive — это 100% фановая штука для новаторов и early adopters. Мы понимали, что приложение на гарнитуре, которая стоит $3500 и продаётся только в США, увидит человек 10. Но очень хотелось «потрогать» VisionOS, тем более, что тема AR/VR-приложений набирает популярность благодаря новой платформе.

Кстати, насчёт 10 пользователей мы ошиблись! Как думаете, сколько сейчас пользователей у приложения? Первому, кто в комментариях отгадает точное количество установок на сегодняшний день, подарим нашего прикольного гуся!

Если хотите работать над проектами 3D-карт, у нас как раз открыты вакансии QA Automation и C++ инженера.

© Habrahabr.ru