Fortnite

Технический блог про выпуск Fortnite для Android

06.09.2018
Кто: разработчики Fortnite

ВСТУПЛЕНИЕ

9 августа мы выпустили бета-версию Fortnite для Android на некоторых устройствах от наших партнёров из компании Samsung. Несколько дней спустя мы начали рассылать приглашения владельцам устройств с Android от других производителей смартфонов. В ходе бета-тестирования мы узнали много важной информации о производительности, безопасности, совместимости с устройствами и распространении Fortnite для Android с помощью программы установки Fortnite. Сегодня мы подробно расскажем о подготовке к выходу игры, об уже проделанной работе и о том, что ждёт версию для Android в ближайшем будущем. 

СТАТИСТИКА

Игра Fortnite для Android вызвала огромный интерес публики. За первые три недели после выхода к бета-тестированию присоединились 23 млн пользователей и более 15 млн установили наш файл приложения. Сейчас версия для Android доступна только по приглашениям, но доля людей, которые получили приглашение и стали игроками, примерно та же, что и во время бета-тестирования версии для iOS.
 

УСТРОЙСТВА И ОПТИМИЗАЦИЯ


Новые технологические задачи

Выпуск одной и той же игры на нескольких платформах с поддержкой кроссплатформенной игры стал для нас уникальной технической задачей. Обычно, адаптируя игру для мобильных платформ, разработчики упрощают не только наполнение, но и игровой процесс, чтобы уложиться в ограничения, установленные платформой. Можно, например, сократить дальность прорисовки объектов, чтобы уменьшить нагрузку на графический чип. Но в Fortnite владельцы устройств с Android могут сражаться в одном и том же матче с друзьями, играющими на ПК и консолях, поэтому нужно прорисовывать всё, что влияет на игровой процесс.

Подготовка к выходу игры на Android

С января 2018 года над «Королевской битвой» Fortnite для Android трудилась большая команда. Мы делали упор на производительность при визуализации, стабильность приложения и экономию оперативной памяти, но разнообразие устройств с Android, обилие версий операционной системы и драйверов стали для нас серьёзной проблемой.

Выход Fortnite на Android стал возможным благодаря тесному сотрудничеству с партнёрами. Без их усилий, знаний и опыта мы бы точно не справились.

Мы активно работали с Samsung над отладкой и оптимизацией Fortnite для их устройств. Samsung отправила своих специалистов в наши филиалы, расположенные по всему миру. Они работали напрямую с нашими программистами над усовершенствованием приложения и анализом производительности, а также внесли множество полезных изменений в нашу систему визуализации на базе Vulkan. Используя специальные тестовые смартфоны и собственный инструментарий, специалисты Samsung выявили уязвимые места, связанные с быстродействием и расходом памяти, и помогли устранить их. Кроме того, вместе с Samsung мы разработали простой и надёжный способ установки игры на телефоны этой компании.

Технические специалисты Google также посетили наши офисы и помогли улучшить Fortnite. Они нашли несколько ключевых точек для оптимизации, указали на утечку памяти и помогли разработать систему сглаживания изображения на базе OpenGL для Android. Программисты Google очень талантливы, они стремятся сделать платформу Android как можно более удобной для разработки игр и постоянно совершенствуют её.

Кроме того, мы работаем над тестированием и оптимизацией Fortnite с целым рядом других партнёров, в том числе ARM, Qualcomm, Imagination Technologies, Razer, HiSilicon и не только.
 

Фрагментация

На базе Android работают многие смартфоны от десятков разных компаний. В основе каждого устройства — однокристальная система, состоящая из нескольких микропроцессоров и графических процессоров. Сейчас распространены несколько семейств однокристальных систем, например Snapdragon компании Qualcomm (71% всех поддерживаемых устройств) с графическим процессором Adreno, а также серии Exynos компании Samsung, MT компании MediaTek и Kirin компании HiSilicon, использующие графические процессоры Mali с архитектурой ARM. В каждом устройстве — свой, слегка модифицированный вариант операционной системы Android, и почти все производители вносят свои изменения в планировщик ядра и функции управления электропитанием. У разных устройств с одной моделью графического процессора отличаются версии графического драйвера. Таким образом, два смартфона с одинаковым аппаратным наполнением могут разительно отличаться по производительности, и у каждого из них могут быть свои технические проблемы.

Мы были приятно удивлены, когда увидели, что новейшая версия Android установлена на большем количестве устройств, выпущенных за последние 2 года, чем мы ожидали. Сейчас, пока идёт бета-тестирование и игра предъявляет высокие требования к платформе, 92% игроков в Fortnite используют Android версии 8 (Oreo) или более новую, у примерно 8% установлена Android 7 (Nougat), и лишь менее 0,5% игроков используют версию Android, вышедшую в 2015 году или раньше. Доля устройств, которым более 2 лет, очень небольшая. Производители этих устройств должны выпустить для них специальные обновления и договориться с операторами мобильной связи в разных странах мира о совместной разработке и распространении этих обновлений.

Чтобы не запутаться в этом многообразии, мы разработали иерархию профилей устройств для Unreal Engine. Для начала мы создали четыре профиля быстродействия: низкий, средний, высокий и эпический. Эти профили позволяют масштабировать запросы программного ядра, чтобы игра запускалась на устройствах с разными характеристиками быстродействия. Для низкого профиля дальность прорисовки сокращается до минимально допустимых значений и отключаются все дополнительные графические эффекты. Для эпического профиля, рассчитанного на новейшие модели смартфонов, доступна максимальная глубина прорисовки и все возможные детали: тени, листва и прочее.

Помимо этого, у нас есть несколько профилей для графических процессоров, например для Adreno 54x и Mali G72. Они подобраны с учётом производительности каждой модели и содержат оптимизированный код или обходные решения для этих процессоров. Наконец, мы подготовили набор профилей для разных устройств, будь то Samsung Galaxy Note 9 Adreno или Google Pixel 2 XL. Этот последний уровень профилей устройств позволяет улучшить оптимизацию и решить дополнительные проблемы, возникающие на конкретных моделях. При запуске игра определяет параметры устройства (модель, версию ОС, версию графического драйвера) и выбирает соответствующий профиль.
 

Производительность при визуализации

Поддерживать высокую частоту смены кадров нам больше всего мешала нагрузка на центральный процессор при визуализации. Версия для Android тратит гораздо больше ресурсов ЦП на обработку графики по сравнению с ПК, консолями и iOS. Новейшие устройства с Android, например смартфон Galaxy S9 с процессором Adreno, способны обрабатывать более 1500 команд отрисовки для каждого кадра. Устройства предыдущих поколений обрабатывают значительно меньше команд. Для средних настроек графики устройство должно обрабатывать примерно 600 команд, а для минимальных — в среднем 400.

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

Кое-какой прирост производительности дала оптимизация нашей системы визуализации на базе OpenGL, но мы даже не ожидали, что наибольшую пользу принесёт один из методов оптимизации памяти — эмуляция uniform-буфера. UE4 поддерживает эту технологию уже много лет, она используется для устройств с OpenGL ES2, в которых нет встроенной поддержки uniform-буфера (он же буфер констант). Вот как это работает. Во время компиляции шейдеров мы рассчитываем все константы для шейдера и вносим их в массив, к которому потом обращается шейдер. Мы также создаём таблицу соответствия, которая указывает программе, где взять константы в uniform-буфере и как разместить их в массиве. Во время работы программы мы храним uniform-буфер в доступной области памяти ЦП, копируем значения в промежуточный буфер с помощью таблицы соответствия, а затем передаём все константы, единожды вызвав функцию glUniform4fv.

Мы не до конца понимаем причину, но эмуляция uniform-буфера позволила нам сэкономить ощутимое количество времени для драйвера. Возможно, драйвер пытается сделать нечто подобное сам, но наш алгоритм быстрее. Кроме того, поскольку мы создаём и занимаем меньше ресурсов, драйверу не нужно столько времени на постоянное управление этими буферами. В любом случае, такой подход позволил нам сэкономить от до 10% до 15% времени на расчёты в драйвере.
 

Vulkan

Vulkan — новейший графический API (интерфейс прикладных программ) для Android, позволяющий добиться высокой производительности и открывающий низкоуровневый доступ к аппаратному обеспечению. В 2016 году мы вместе с Samsung создали демоверсию ProtoStar, чтобы показать способности этого высокопроизводительного графического API для Android. Поскольку в Fortnite требуется отображать множество объектов в каждом кадре, было бы логичным воспользоваться Vulkan. Но на деле всё оказалось не так просто.

Сейчас Vulkan не входит в число обязательных API для Android, и мы не могли быть уверены, что он есть на всех устройствах. Поскольку мы разрабатывали игру только для новых моделей, это обстоятельство не мешало нашим планам. Но мы столкнулись с ошибками и падением производительности из-за несовершенных драйверов Vulkan, поэтому пришлось признать, что на большинстве устройств OpenGL работает быстрее и стабильнее, чем Vulkan. И это неудивительно, ведь разработчики оптимизировали поддержку OpenGL на протяжении десяти лет. Vulkan — более сложный API, и пройдёт несколько лет, прежде чем он достигнет такого же уровня.

Впрочем, мы всё же выпустили игру с поддержкой Vulkan для Samsung S9+ (Adreno) и Note 9 (Adreno). Тесно сотрудничая со специалистами Samsung, мы оптимизировали поддержку Vulkan в UE4, добившись прироста производительности в среднем на 20% по сравнению с OpenGL. Мы будем и впредь работать с нашими партнёрами, чтобы поддержка Vulkan появилась на других устройствах. Эта оптимизация порадует не только поклонников Fortnite для Android, но и улучшит драйвер Vulkan для всех разработчиков игр.
 

Оперативная память

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

У нас нет стандартного объёма выделенной памяти, от которого мы могли бы отталкиваться в работе. У каждого устройства этот показатель свой, разные приложения работают в фоновом режиме, действуют разные правила по остановке приложения, если оно начинает тратить слишком много ресурсов. У нас также нет API, позволяющего рассчитать этот объём. Нам пришлось собирать такую статистику самим. В порядке эксперимента мы запустили матч и начали загружать оперативную память, чтобы увидеть, в какой момент ОС остановит процесс. На только что перезапущенном Samsung Galaxy S8 (Mali), где нет никаких других приложений, мы успели занять 3 из 4 ГБ памяти смартфона, прежде чем приложение было закрыто. На Google Pixel 2 нам удалось занять лишь 1,8 из 3,6 ГБ.

Система, особенно графический драйвер, резервирует большой объём оперативной памяти под наши нужды. UE4 отслеживает всю память, которую мы запрашиваем у ОС напрямую, и примерно оценивает расход памяти для графического процессора, но у нас нет чёткого понимания, какой объём памяти зарезервировал драйвер. С помощью экспериментов мы установили, что драйвер резервирует львиную долю операционной памяти для шейдеров Fortnite.

Мы применили вышеупомянутую эмуляцию uniform-буфера как раз для оптимизации памяти. OpenGL требует, чтобы приложение могло с помощью запроса определить местоположение любого элемента uniform-буфера. Например, в OpenGL можно узнать смещение матрицы LocalToWorld в uniform-буфере Primitive. Для этого драйвер обязан хранить определённые метаданные, в частности таблицу смещений, где есть строчки с названиями всех элементов, и так для каждого приложения.

Fortnite использует множество разных шейдеров. В среднем, за игру задействуется около 2000 разных шейдерных микропрограмм. Драйвер хранит метаданные для каждой из них, расходуя в сумме огромное количество памяти. Переход на эмуляцию uniform-буфера в Fortnite позволил нам сэкономить более 400 МБ!

Когда мы только выпустили Fortnite для Android, по результатам нашего внутреннего тестирования мы укладывались в доступный объём памяти на выбранных устройствах. Мы ставили эксперименты, в ходе которых включали навигацию в картах Google и транслировали музыку, чтобы убедиться, что Fortnite будет работать без проблем. Однако после запуска мы обнаружили, что многие игроки столкнулись с критическими ошибками или низкой производительностью из-за нехватки памяти.

Когда у смартфона с Android заканчивается оперативная память, он пытается освободить часть ресурсов, закрывая неиспользуемые приложения. Однако, как оказалось, есть целый ряд упрямых фоновых приложений и сервисов, которые перезапускаются, едва ОС успевает их закрыть. Из-за этого ситуация становится только хуже! Android закрывает приложение, чтобы освободить память, но оно перезапускается и вновь занимает этот объём памяти. Более того, запуск и остановка приложений увеличивают нагрузку на центральный процессор. В итоге мы не только не освобождаем память, но ещё и напрасно тратим ресурсы ЦП.

Мы обновили процедуру тестирования и установили на устройства популярные приложения, которые есть у большинства пользователей, чтобы быстрее найти источник проблемы, но нужно было что-то сделать с расходом памяти. Нам удалось установить, что проблемы возникают у пользователей с высокими и эпическими настройками видео на устройствах с последними моделями Snapdragon компании Qualcomm и 4 ГБ памяти. Как и прежде, больше всего памяти уходило на шейдеры. В качестве временной меры мы отключили тени. Это сократило количество используемых шейдеров, поскольку теперь не требовалось искать варианты и заниматься фильтрацией карт теней. Мы даже добавили LRU-кэш для шейдеров. Он хранит только те шейдеры, которые нужны для отрисовки текущей сцены, находящейся в памяти. Все прочие шейдеры хранятся в памяти в сжатом виде. При необходимости они распаковываются и передаются драйверу.
 

Планы на будущее

Сейчас мы работаем над тем, чтобы игра плавно работала на всех поддерживаемых устройствах и боремся за освобождение оперативной памяти, стараясь повысить качество графики и стабильность. Затем мы займёмся решением проблем с совместимостью, вроде проблем со звуком. Так, в обновлении 5.40 мы исправили подобные проблемы, возникающие на многих устройствах, и увеличили список поддерживаемых устройств. Мы также планируем добавить ряд параметров, чтобы игроки смогли самостоятельно настроить графику и решить, что им важнее, красота или быстродействие.

Мы продолжим совершенствовать поддержку Vulkan и делать её доступной на новых устройствах. Для этого мы будем тесно сотрудничать с производителями смартфонов для оптимизации их драйверов и UE4. В долгосрочной перспективе работа над Vulkan позволит нам улучшить быстродействие всех игр на основе UE4, выпускаемых для Android.

Мы постараемся добавить поддержку более старых и медленных телефонов, но большого смысла оглядываться назад нет. Каждый год новые передовые смартфоны становятся на 50% быстрее предыдущих моделей. Fortnite сносно работает на телефонах, выпущенных два года назад, хорошо — на моделях прошлого года и отлично — на моделях этого года. Можете себе представить, как круто будет выглядеть Fortnite на смартфонах, которые появятся через год!

image2.png


Наконец, многие доработки, внесённые нами в UE4, уже доступны в версии 4.20. Остальные появятся в версии 4.21, и мы продолжим делиться нашими достижениями со всеми разработчиками, использующими UE4.
 

БОРЬБА С ВРЕДОНОСНЫМИ ПРОГРАММАМИ

Ещё до того, как мы анонсировали выпуск Fortnite на Android, в интернете начали появляться неофициальные сайты с «Fortnite для Android», где под видом игры людям предлагали скачать вредоносные или мошеннические программы. Как только мы узнаём о существовании очередного такого сайта, мы стараемся удалить его, обращаясь напрямую к владельцу или провайдеру хостинга, а также убрать объявления или видеоролики, рекламирующие его. Независимо от того, распространяет сайт вредоносные программы или нет, мы считаем любую попытку распространения Fortnite для Android, будь она настоящая или мнимая, недопустимой. Законный доступ к Fortnite для Android предоставляет только официальная программа установки Fortnite от Epic.
 
Сейчас Epic предприняла действия в отношении уже 47 сайтов с мнимым Fortnite для Android, многие из которых принадлежат одним и тем же мошенникам. Мы продолжаем следить за ситуацией и стараемся удалить эти сайты либо ограничить к ним доступ, используя сеть наших партнёров по борьбе с мошенничеством (среди которых провайдеры интернета, разработчики браузеров и антивирусных приложений), которые могут добавить в браузер предупреждения, подобные этому:

Image1.png
 
Мы активно ищем новые сайты с вредоносными программами и создали для этого отдельную внутреннюю команду. Кроме того, чтобы расширить охват, мы обратились за помощью к стороннему агентству по охране авторских прав и борьбе с мошенничеством. С его помощью мы отслеживаем регистрацию новых доменных адресов с подозрительными названиями, чтобы, если под ними разместят вредоносные сайты, Epic смогла принять меры вплоть до обращения в суд.

ЗАКЛЮЧЕНИЕ

Fortnite для Android — во многом первопроходец игровой индустрии. Это первая игра для консолей и ПК, вышедшая на Android с полноценной поддержкой кроссплатформенной игры. Это первая популярная игра, которая распространяется не через Google Play. Мы потратили немало сил на разработку и многому научились, и, судя по тому, что к игре присоединились уже 15 млн пользователей Android, этот подход может оказаться очень успешным. Что ещё важнее, итоги работы над ПО, проделанной нами при создании Fortnite для Android, станут доступны всем разработчикам Unreal Engine в версии 4.21.