Всем привет! Меня зовут Александр Гришин, я работаю в студии IT-Territory (Mail.Ru Group) специалистом по тестированию. Я занимаюсь разработкой Android-версии «Эволюции: Битва за Утопию». iOS-аудитория с интересом встретила новинку весной этого года, и мы уже готовимся к первым впечатлениям Android-юзеров. В статье я расскажу о том, как мы портировали игру на Android и с какими трудностями и нюансами столкнулись в процессе.
«Эволюция» на iOS
Если взглянуть на мобильные игры в целом, то сейчас на рынке мало проектов, подобных «Эволюции» — больших, сложных, затратных, требующих для разработки большую команду. Создание игр с таким количеством механик, каждая из которых, по сути, является отдельной миниигрой, процесс долгий и кропотливый: нужно не только их сделать, но потом еще и соединить, притереть друг к другу, сделать так, чтобы все вместе работало как надо и вызывало у пользователя интерес, а не недоумение. Таких игр мало даже на iOS, для которого студии охотнее создают игры, и практически нет на Android.
Сложное многообразие
Android – платформа специфичная. Начать хотя бы с того, что у iOS всего пять разрешений экранов, что, разумеется, делает разработку приложения проще. У Android число разрешений идет на сотни, если не тысячи. С технической точки зрения, когда рисуют графический интерфейс для этой платформы, его привязывают к углам. Но иногда его растягивают, а не рисуют пиксель в пиксель – например, фоны, отчего страдает графика или нарушаются пропорции. В iOS мы всегда знаем, как у нас будет выглядеть картинка; в Android все далеко не так просто.
На рынке Android-устройств масса различных моделей с различной производительностью, но при этом здесь контролировать установку на различные аппараты проще; например, в iOS сложно ограничить устройства, на которых приложение может запускаться. Вы можете отметить в описании приложения, что iPhone четвертого поколения его не поддерживают. При этом оно запускается на этих устройствах, в него можно играть, но, в принципе, никто не гарантирует, что оно не будет вылетать или делать еще что-то не по плану. В Android можно указывать конкретные девайсы, для которых человек скачивает игру, и выкладывать много дистрибутивов для разных графических чипов.
Для iOS мы выкладываем один-единственный дистрибутив. Некоторые выкладывают два, один для планшетов и второй для смартфонов. В Android нужны различные дистрибутивы, которые собираются в зависимости от чипа, сжатия текстур и других параметров. В некоторых играх необходимо сделать около 5-6 различных сборок, что, конечно, усложняет процесс деплоймента приложения. Когда делается несколько дистрибутивов под разные GPU, мы загружаем их в Google Play; когда клиент скачивает приложение, цифровой магазин сам подбирает билд под GPU устройства и выдает его.
Все графические чипы iPhone принадлежат одному семейству PowerVR, поэтому мы всегда можем очень точно предсказать производительность игры. На Android есть четыре распространенных графических чипа, которые работают совершенно по-разному. Мы столкнулись с тем, что приложение на этой платформе настолько тормозило, что пришлось переделывать шейдеры, снижать их качество или вообще отключать. В Android спекуляр считается в вершинном шейдере, а в iOS — в пиксельном. Так что мы воспользовались стандартным методом повышения производительности ценой некоторого ухудшения картинки — переносом расчетов из пиксельного шейдера в вершинный.
Еще одна сложность, с которой мы столкнулись при портировании «Эволюции»: на Android нет совместимого со всеми устройствами формата сжатия текстур с альфаканалом (ETC1 (4bit) vs PVRTC4/2 (4/2 bit with alpha). Несжатые текстуры – это не только лишняя трата памяти и увеличение размера приложения, но еще и более длительная загрузка приложения, и потеря производительности. С технической точки зрения отсутствие сжатия текстур с альфа-каналом является очень, очень большим ограничением Android-платформы. В стандарте графического API OpenGL ES 2.0. прописан единственный формат ETС1, который уже устарел и не содержит альфа-канал. На iOS есть очень хороший графический чип: помимо того, что текстуры с ним занимают меньше памяти, они еще и быстрее грузятся. Когда вы перегружаете сцены с большим количеством текстур в игре, на iOS это происходит мгновенно, а на Android с заметной задержкой, которая в нашем случае доходила до 1.5 секунд. Увы, пришлось работать с тем, что есть, или использовать форматы сжатия, специфичные для конкретной аппаратной платформы: PVRTC, DXT, ATC, ETC. В принципе, проблему сжатия с альфа-каналом разработчики Android планируют решить в следующем стандарте OpenGL ES 3.0: там появится хороший передовой формат сжатия (ASTC), и всем сразу же станет легче жить.
Это основные сложности при портировании приложения с iOS на Android. Были и другие проблемы, например, предельный размер APK. У Android этот показатель равен 50 Mb, при том что на iOS ограничения существуют только для cellular загрузки. iOS-версия игры представляет собой один файл размером примерно 420 МБ; на Android игра разбита на маленький APK-файл, который впоследствии догружает большой OBB-файл, в котором находится игра. Впрочем, Unity делает большую часть работы за вас.
Как это было у нас
У нас, можно сказать, исторически сложилось, что в первую очередь мы разрабатываем игру для устройств Apple и потом портируем ее. Конечно, можно разрабатывать игру сразу под две платформы, а можно под три. «Джаггернаут: Месть Соверинга» мы, например, выпускали еще и просто под десктопный МАС или OSX.
Портирование с iOS на Android сильно упрощается, если игра сделана под Unity. Достаточно просто запустить ее на новой платформе – и сразу становится очевидно, где нужно пройтись напильником и что нужно доделать, чтобы результат выглядел нормально. Если игра не под Unity, то у меня плохие новости: по факту вам придется заново ее написать.
На портирование «Эволюции» на Android у нас ушло около двух месяцев. Как я уже говорил, игра весьма сложная, как для разработки, так и портирования. Дело в том, что в ней объединены как бы несколько различных геймплеев. Персонажи передвигаются по карте, сражаются с монстрами, разгадывают загадки – для каждого из этих занятий есть свой интерфейс, своя механика. И, разумеется, все это добро грузится прямо во время игрового сеанса – то есть для нас было важно, чтобы «Эволюция» продолжала «летать» после перевода на новую платформу.
Самая большая проблема, с которой мы столкнулись, – выдержать ту же самую производительность в бою, которая была у игры на iOS. Чтобы добиться этого, мы написали новые шейдеры, которые дали необходимый прирост скорости, несильно ухудшив картинку. Нам даже удалось спасти «честные» тени от персонажей! Переделывать графические ассеты (сцены, модели, анимацию) практически не пришлось.
Вторая большая (и даже более трудоемкая) часть работы – 2D-часть игры, которая в «Эволюции» даже больше, чем 3D. Тысячи разрешений экрана Android (против всего нескольких у iOS) и отсутствие такого замечательного формата сжатия текстур, как PVRTC (доступного на любом устройстве iOS), приводят к большому количеству кропотливой работы. В «Эволюции» десятки экранов, фонов, флипбук-анимаций (flip book) и тысячи спрайтов, упакованных в десятки атласов. Тут пришлось что-то сжимать, что-то растягивать, что-то перепаковывать.
Со всеми изменениями, которые претерпевает графика во время портации, вес игры меняется – в худшую сторону для Android. На iOS графика сжимается в размере в 8 раз. Там есть совершенно чудесный алгоритм PVRTC4, который позволяет из 32-битной графики с альфа-каналом делать очень пристойного качества 4-х битную. Поскольку не всю графику на Android удается сжать так качественно, как на iOS, то она занимает больше места на диске.
Много где требовалось ручной настройки; несмотря на то, что мы выбрали некое общее решение, пришлось немало вещей дорабатывать руками. Например, уже упомянутая проблема с различными экранами: пришлось учитывать эту особенность Android и как-то решать ситуацию. Конечно, переписывать все под каждый возможный экранчик не пришлось. На iOS у нас было всего два масштаба, оба кратные двум – именно поэтому у нас не было особых проблем нарушением пропорций и размытием графики. Как правило, в Android берут некое среднее разрешение, и все остальное масштабируют под него. Изменение разрешения в первую очередь сказывается на двухмерной графике: у нас к ней относятся различные элементы интерфейса, кнопки и прочее. Пришлось перебирать эти детали вручную, пережимать текстуры, менять размеры графических элементов в основном интерфейсе.
Всего для «Эволюции» мы сделали четыре дистрибутива. При этом позже нам пришлось отказаться от одного из них – игра пока не поддерживает Tegra. Вообще портация на Tegra, особенно старых поколений – это целое приключение. Как правило, когда люди могут графически интенсивную 3D-игру портировать на Tegra, они потом едут куда-нибудь на профессиональную конференцию и делают об этом доклад. Это ювелирная и специфичная работа, когда разработчик добивается увеличения fps с 10 до 30, просто поменяв порядок отрисовки разных объектов на экране.
Современные мобильные GPU с высоты птичьего полета
Все GPU, представленные на мобильном рынке, работают немного по-разному. Их можно разделить на 3 класса: tile-based deferred rendering (TBDR) — PowerVR; tile-based rendering (TBR) — Adreno, Mali и immediate mode rendering (IMR) — Tegra.
PowerVR со своим TBDR сильнее всего отличается от IMR, который является обычным решением для десктопов. PowerVR работает так: он разбивает весь экран на маленькие тайлы размером 16х16 пикселов и отрисовывает туда всю геометрию, попавшую в этот тайл. Это происходит в сверхбыстрой памяти, находящейся внутри чипа. В процессе отрисовки он отбрасывает все пиксели, которые не будут видны на финальной картинке (например, перекрытые другими непрозрачными объектами), и потом текстурирует и рассчитывает освещение только для тех пикселей, которые точно будут видны на экране. На сегодняшний день это одно из самых экономичных и быстрых решений, и, хотя у него есть свой набор недостатков, с точки зрения разработчиков мобильных игр он наиболее оптимален. Из очевидных достоинств он очень быстро делает альфа-смешение, антиалиасинг, фильтрацию текстур и совершенно нечувствителен к порядку отрисовки непрозрачных объектов, мип-маппингу и так далее, а замечательный формат сжатия PVRTC еще больше уменьшает нагрузку на память. Другими словами, разработчикам не нужно ничего особенно оптимизировать — нужно просто придерживаться определенного бюджета количества вершин, не злоупотреблять прозрачностью и не использовать альфа-тест, который ломает весь процесс TBDR.
IMR рисует все, используя лишь приблизительные оптимизации отсечения невидимых поверхностей (Early Z-cull), поэтому очень чувствителен к порядку отрисовки непрозрачных объектов. Unity тут, к сожалению, ничем помочь не может — разработчик должен сам разобраться, какие объекты на сцене будут занимать больше экранного места, и сказать Unity рисовать их в первую очередь (render queue). Поскольку затеняются все пиксели, то пиксельным шейдерам достается больше работы.
TBR чипы работают примерно так же, как IMR, но разбивают экран на тайлы для уменьшения нагрузки на память.
NVIDIA продолжает выпускать новые виды, скоро будет уже Tegra K1, так что это вполне интересное направление, но, к сожалению, там совершенно другой подход, и из-за этого все равно будет какая-то разница при портировании. Из мелких деталей: допустим, если в iOS отключить на всех текстурах mipmap, то производительность падает на 2-3 fps. Если это сделать на Android, то производительность падает на целый порядок. Этих тонкостей очень много: если вы собираетесь оптимизировать игру для каждого из чипов, то будьте готовы к штудированию толстенных мануалов по оптимизации от фирм-производителей, долгому профайлингу и экспериментам. Кто-то делает эту работу и читает потом доклад на конференции; мы решили не копать так глубоко, а просто выбрали перечень устройств, для которых собрались разрабатывать дистрибутивы, протестировали результат и залили удачные версии в магазин. Увы, не каждый обладатель Android-устройств сможет поиграть в «Эволюцию», но мы «прикрыли» максимально возможное число устройств. В целом, игру поддерживает приблизительно 1000 мобильных устройств с Android.
Вот и вся история. Спасибо за внимание, если у вас есть вопросы – задавайте в комментариях, c удовольствием отвечу на них.
Автор: Frysed