УДК 004.92

Оптимизация и повышение производительности игровых движков для Android

Боровиков А.И.*1, Зори С.А.*2

*1 магистр кафедры программной инженерии им. Л. П. Фельдмана, Донецкий национальный технический университет,
e-mail: aleksey.borovikov.00@mail.ru, SPIN-код: 2472-1006
*2 д.т.н., проф. кафедры программной инженерии им. Л. П. Фельдмана, Донецкий национальный технический университет,
e-mail: ik.ivt.rec@mail.ru, OrcID: 0000-0003-4018-234X, SPIN-код: 3565-6330

Аннотация

В статье представлен анализ влияния производительности игры на «комфорт» для пользователей, проведён анализ возможных проблем оптимизации движка, тонкостей языка программирования Java, которые могут повлиять на производительность, и особенностей написания игр под мобильные приложения. В дальнейших исследованиях планируется проверить на практике приведённые методы и представить метрики в виде графиков и диаграмм с целью их усовершенствования.

Ключевые слова: Java, CPU, GPU, FPS, время простоя процессора, циклы, потоки, память, рендер, Vulkan, тепловая нагрузка, энергопотребление, OpenGL, libGDX, JVM GC.

Введение

Производительность является важным компонентом любой игры: от неё зависит популярность, комфорт пользователя и общее впечатление. Под производительностью обычно понимается средний уровень FPS (Frames Per Second) — числа кадров в секунду за определённый промежуток времени. Кадры представляют собой изображения, которые обрабатывает графический адаптер по команде центрального процессора. Чем больше кадров демонстрируется, тем плавнее и комфортнее игра [1].

Несмотря на распространённое мнение, немногие игроки требуют очень высоких значений FPS. Для большинства пользователей достаточно среднего уровня около 30 кадров в секунду, а для некоторых и меньше. Исследования компании Lesta Studio [2] показывают, что для общей совокупности пользователей связь между производительностью и субъективным комфортом игры относительно слаба (рисунок 1).

Диаграмма зависимости между восприятием комфорта и средним FPS
Рисунок 1 – Диаграмма зависимости между восприятием комфорта и средним FPS

Уровень комфорта зависит от жанра игры и индивидуальных предпочтений игрока. Многие консольные проекты работают на частоте 30 FPS, однако при таких показателях картинка воспринимается недостаточно плавной, а отклик на действия игрока запаздывает, что ухудшает ощущение «погружения» в игру. Для казуально-аркадных игр комфортным считается диапазон от 40 FPS, для шутеров от первого лица, стратегий, ритм-игр и MOBA часто требуется 60–100 FPS, а выше 100 FPS ориентируются киберспортсмены и любители соревновательных шутеров.

Если не учитывать потребности профессиональных игроков, можно считать комфортным для большинства пользователей средний показатель около 60 FPS, который выступает своеобразным «минимумом комфорта».

Влияние на производительность

На производительность игры влияет ряд факторов:

  1. Клиентское ПО, включая операционную систему. Если система загружена фоновыми процессами или параллельно запущены ресурсоёмкие программы, ресурсов для игры может оказаться недостаточно.
  2. Конфигурация аппаратного обеспечения. От комплектующих устройства напрямую зависит производительность.
  3. Настройки графики. Пользователи часто настраивают графику вручную или используют пресеты, однако это не гарантирует оптимального соотношения качества и производительности.
  4. Сетевые проблемы. Для сетевых игр важны стабильность и пропускная способность канала. Проблемы на стороне провайдера, большое количество беспроводных клиентов, неоптимальный маршрут передачи трафика и некачественное оборудование могут вызывать лаги и падение производительности.
  5. Модификации игры. Сторонние моды нередко ухудшают производительность: снижают средний FPS и вызывают резкие провалы, где «чистый» клиент работает стабильно.
  6. Скорость работы приложения и движка. Существует множество игровых движков со своими особенностями архитектуры и поддерживаемых эффектов. На производительность влияет также язык программирования, на котором написан движок, и особенности управления ресурсами.

Способы оптимизации кода

Для того чтобы игровой движок выдавал максимальное количество FPS, разработчику необходимо не только эффективно работать с самим движком, но и учитывать особенности языка, на котором он реализован, и принципы распределения ресурсов [3]. Ниже приведены общие методы оптимизации, применимые во многих ситуациях.

  1. Минимизация влияния объектов за пределами экрана. Важно уменьшать объём вычислений за счёт оптимизации отрисовки. Часто это делает сам движок или графический процессор, но можно дополнительно разделить объект на графический слой и слой данных. Тогда объекты вне области видимости можно перестать отрисовывать.
  2. Независимость логики от частоты кадров. Обновление большого количества объектов в каждом кадре сильно нагружает процессор. Желательно отделять логику отрисовки и вызывать функции рендера только при изменении состояния объекта.
  3. Хеширование вычислений. Для повышения скорости можно кэшировать результаты тригонометрических и других ресурсоёмких функций, храня их в таблицах и обращаясь к ним вместо вычислений «на лету».
  4. Использование времени простоя процессора. Некоторые вычисления, не зависящие от времени (например, изменение погодных условий), можно выполнять, пока пользователь не активно взаимодействует с игрой — читает текст, находится в меню и т.п.

Оптимизация движка на основе языка Java

Отдельное внимание уделяется оптимизации кода с учётом особенностей языка программирования Java и работы движков, основанных на нём (например, libGDX) [4].

  1. Циклы. При обходе больших массивов (списков объектов, врагов и т.п.) полезно использовать обратный цикл for, который избавляет от проверки размера массива на каждой итерации, или цикл while, если это возможно.
  2. Потоки. Тяжёлые операции следует выносить в отдельные потоки и не выполнять сложную логику в потоке отрисовки (GLThread). Нарушение этого правила приводит к подвисаниям интерфейса и проблемам с загрузкой текстур.
  3. Память. Важно своевременно освобождать ресурсы. Сборщик мусора JVM не управляет памятью OpenGL, поэтому текстуры и другие объекты должны удаляться вручную, иначе возможны утечки памяти.
  4. Пакетная отрисовка. Частые вызовы начала и конца пакетной отрисовки (SpriteBatch, ShapeRenderer) увеличивают накладные расходы. Лучше визуализировать все спрайты и фигуры за один проход.
  5. Избегание тяжёлых методов. Некоторые методы (например, проверки пересечений) стоит вызывать только после предварительной проверки близости объектов, а не для всех элементов массива.
  6. Визуализация только видимых элементов. Логику объектов можно обновлять всегда, но вызывать метод рисования только если объект находится в пределах экрана.
  7. Размещение переменных. Объявление объектов внутри циклов рендеринга может приводить к «фризам». Лучше объявлять их вне циклов и переиспользовать. Для примитивных типов влияние меньше.
  8. Использование паттернов проектирования. Шаблоны Singleton, Factory и другие помогают упорядочить архитектуру, уменьшить количество лишних экземпляров и повысить читаемость кода.

Оптимизация игр для смартфонов

Мобильные устройства имеют ограниченные ресурсы и отличающуюся от настольных систем архитектуру, поэтому при разработке игр для Android необходимо учитывать ряд дополнительных факторов [5, 6].

  1. Скорость загрузки. Игроки хотят как можно быстрее перейти к геймплею. Сократить время загрузки помогают: ленивая загрузка ресурсов, уменьшение размера ассетов, использование эффективных методов сжатия (например, zlib).
  2. Размещение потоков на ядрах процессора. На многих устройствах кэши L1 и L2 привязаны к конкретным ядрам. Для максимизации попадания в кэш важно закреплять потоки с большим объёмом работы за одними и теми же ядрами.
  3. Распределение кратковременных задач. Краткие операции лучше переносить на менее мощные ядра. Это снижает тепловую нагрузку и энергопотребление без заметной потери отзывчивости.
  4. Контроль тепловой нагрузки. При перегреве устройства процессор и графический адаптер снижают частоты, что резко ухудшает производительность. Необходимо отслеживать температуру с помощью специальных API и при перегреве уменьшать частоту кадров, упрощать графику и уменьшать сетевую активность.
  5. Оптимизация пользовательского интерфейса. Важно учитывать небольшой размер мобильных экранов и избегать перегруженности UI. Следует обновлять только изменившиеся элементы, ограничивать число текстур и слоёв, переносить анимации на GPU, использовать отсечение невидимых объектов и, по возможности, Vulkan.
Пример неоптимального назначения потоков процессорам устройства
Рисунок 2 – Пример неоптимального назначения потоков процессорам устройства
Пример кадра с перегруженным пользовательским интерфейсом
Рисунок 3 – Пример кадра с перегруженным пользовательским интерфейсом

Выводы

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

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

Литература

  1. Каким должен быть комфортный FPS в играх [Электронный ресурс]. – Режим доступа: https://andpro.ru/blog/pc/kakim-dolzhen-byt-komfortnyy-fps-v-igrakh/ .
  2. Почему производительность в играх — это не просто средний FPS [Электронный ресурс]. – Режим доступа: https://habr.com/ru/company/lesta_studio/blog/265487/ .
  3. Основы оптимизации кода игр [Электронный ресурс]. – Режим доступа: https://habr.com/ru/post/358176/ .
  4. Optimizing your Game [Электронный ресурс]. – Режим доступа: https://www.reddit.com/r/libgdx/comments/7cw4va/optimizing_your_game/ .
  5. The LibGDX performance guide [Электронный ресурс]. – Режим доступа: https://yairm210.medium.com/the-libgdx-performance-guide-1d068a84e181 .
  6. Best practices for Android game optimization [Электронный ресурс]. – Режим доступа: https://developer.android.com/games/optimize .

Annotation

Zori S.A., Borovikov A.I. Optimization and performance improvement of game engines for Android. The article presents an analysis of the impact of game performance on user comfort, discusses possible engine optimization problems and the specifics of the Java programming language that can affect performance and the development of mobile games. In further research, it is planned to test the described methods in practice and present metrics in the form of graphs and charts in order to improve them.

Keywords: Java, CPU, GPU, FPS, CPU idle time, cycles, threads, memory, render, Vulkan, thermal load, power consumption, OpenGL, libGDX, JVM GC.

Источник: Оптимизация и повышение производительности игровых движков для android / А.И. Боровиков, С.А. Зори // Программная инженерия: методы и технологии разработки информационно-вычислительных систем (ПИИВС-2022) : сборник материалов и докладов IV Международной научно-практической конференции, Донецк, 29–30 ноября 2022 года. – Донецк: Донецкий национальный технический университет, 2022. – С. 46–50.