В этой статье я хочу поделиться с вами нашем опытом разработки мобильной кросс-платформенной (iOS/Android) игры.
Игру мы писали на Unity, а сама графика — спрайтовая. Но многое из сказанного ниже будет справедливо также и для других кросс-платформенных движков, а так же — для полноценного 3D.
Начну я свой рассказ с заблуждения.
Миф о кросс-платформенности.
Когда мы с командой начинали разработку этого проекта на большом и очень кросс-платформенном движке Unity (который также поддерживает Win, Mac, XBox, PS3, PSP, и т.п.) — то мы надеялись на то, что Unity возьмет всю заботу о кросс-платформенности на себя, а наша задача будет только жать «publish» под разные платформы и пить кофе.
Да, конечно же, мы знали о фрагментации платформы, но по большей части заточку под андроид мы ожидали увидеть в области графики (адаптация под разные разрешения, диагонали и dpi) и быстродействия (ясно, что то, что потянет один дроид — другому не под силу).
Но не все так просто.
Память и текстуры.
Если вы уже сталкивались с разработкой мобильных игр, то знаете, что скорее всего, вашим злейшим врагом будет не нехватка ресурсов CPU/GPU, а нехватка памяти. Именно о памяти нужно думать в мобильной разработке всегда и везде.
Например, iPad 2 дает приложению под ресурсы немногим больше 100 Мб RAM. И если вы разрабатываете игру, в которой довольно большое количество спрайтов (уложенных, конечно же, в атласы) — то вы рано или поздно задумаетесь о количестве этих самых атласов и сжатии текстур.
Стандартный атлас, с которым работают все более-менее уважающие себя устройства — это 2048х2048 пикселей. Что в несжатом виде (32 bits per pixel) будет занимать аж 2*2*4 = 16 Мб памяти. Да, есть еще 16 бит на точку, но с одной стороны — это все равно 8 Мб, а с другой стороны — это не всегда приемлемо. Например, на градиентах вы увидите весьма неприятный dithering.
Тогда на выручку приходят форматы сжатия текстур. Под iOS это PVR формата 4 и 2 бита на пиксель. PVR2 страшен как черт, а вот в PVR4 кое-что упаковать можно. 2 Мб для атласа 2х2к — неплохо.
И все бы хорошо, но в андроиде вас ждет сюрприз!
Сюрприз в виде 4х разных чипов, каждый из которых поддерживает свой формат сжатия текстур и не поддерживает другие!
(Здесь, правда, стоит оговориться, т.к. все чипы под андроидом поддерживают еще формат ETC. Но в нашем случае он мало интересен, т.к. это формат без альфа-канала. Да, конечно, можно написать шейдер, компонующий две текстуры (в одной хранить RGB, в другой — A), но это весьма муторно как с точки зрения реализации, так и изрядно усложнит ваш пайплайн подготовки графических ассетов).
Итак, какие чипы радуют нас на дроиде:
* PowerVR (Samsung Galaxy Tab 2) — сжание PVR
* nVidia Tegra, GeForce (Asus Transformer) — сжатие DXT
* Adreno (некоторые Nexus) — ATC
* Mali (все Samsung Galaxy S) — не поддерживает сжатие с альфа-каналом
Так что если вы выпустите под андроид APK, в котором все (или часть) текстур будет пожата в PVR, как бы вы это сделали для iOS, — то столкнетесь с крашами на куче устройств, т.к. если устройство видит неподдерживаемый формат, то пытается его заранее распаковать в 32bpp, а в результате — вылетает по памяти.
Больше всего в этой картине меня удивили флагманы от Самсунга — Galaxy S3. GPU, использующийся там — не поддерживает сжатие с альфа каналом! Но тут спасает то, что андроиды по-другому относятся к памяти. И на мощных устройствах они вполне готовы выделить вам 400 метров под распакованные текстуры. Но только дело ведь не исключительно в памяти! Дело в том, что от размера текстур еще зависит и быстродействие. Ведь гонять все эти мегабайты туда-сюда — тоже удовольствие небыстрое.
Ну да ладно, с Mail — тут уж либо извращаться с шейдерами и 2-мя текстурами, либо забить. Вроде как, оно работает и помещается в памяти.
Но что делать с более слабыми устройствами? А ничего. Только предварительно жать все текстуры в разные форматы, индивидуально для каждого GPU и потом либо делать несколько приложение в Google Play, либо после старта подгружать с сервера нужный пак текстур.
Стоит ли говорить, что все эти танцы с текстурами весьма усложняют пайплайн? А ведь часто в ассеты нужно внести правки. И в результате мы должны будем пережать каждый атлас по несколько раз… Кстати, упаковка одного атласа 2х2к в PVR, например, длится около 10 минут.
Индивидуальные особенности.
В первые дни после запуска проекта, мы начали получать тонны отзывов в гугл плее с уникальными, неповторимыми багами на разных устройствах. И все проблемы были непохожи друг на друга.
Правда, большинство из них объяснились сжатием текстур. Но не все. Кому-то не влезает в память. У кого-то конфликтует с другими поставленными приложениями (есть даже пара топиков, где люди обсуждают, что, например, Asus'овская оболочка любит конфликтовать с приложениями на Unity).
У кого-то — вообще тормозит звук (!).
А вы знали, что у планшетофонов серии Note — по сути — два экрана? Один тачевый (емкостной), а второй — для стилуса (резистивный). И обрабатываются они по-разному. И в Unity, чтобы заработал стилус, — нужно писать отдельный код.
После релиза вы увидите, как каждый, на своем уникальном и неповторимом устройстве неизвестного происхождения, словит какой-нибудь баг и обязательно пожалуется об этом в отзывах.
И предстоит вам копаться в настройках своего проекта в Google Play и руками отключать какие-то заведомо фейловые устройства. Ну, или иметь нереальный пар устройств.
Странные и неподвластные баги.
Думаете, вы все контролируете? А вот фигушки!
В том же Unity то и дело латают какие-то баги, приводящие к крашам под андроидом. Еще совсем недавно некоторые из них были весьма распространенные и фатальные.
А еще есть необъяснимое поведение. Например, игра работает совершенно нормально. Но если ее свернуть, а потом вернуться в нее — то половина текстур заменяется черными квадратами. Что это? Баг Unity? Или ядра конкретного дроида? Неизвестно…
Не забудьте о защите!
Здесь, в отличии от предыдущих пунктов — ничего особо страшного и запутанного нет. Просто, имейте в виду, что любителей покопаться в памяти дроида куда больше, чем таких же на iOS. Так что обязательно верифицируйте платежи (для iOS тоже не помешает). А также — зашифруйте все важные хранимые циферки (количество денег у игрока и т.п.), т.к. программ а-ля ArtMoney под дроид тоже хватает.
А вообще — набирайтесь терпения — и вперед!
Автор: soulburner