Повышение производительности в Unity. Как я поднял показатель FPS с 15 до 60

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Увлекательное путешествие в поисках лучшей производительности на мобильных устройствах

Введение

Я делаю ремейк своей старой игры Loca Deserta: Sloboda Первая версия была написана на Flutter, но сейчас в качестве движка для игры я выбрал Unity.

Я начал работу с нуля и реализовал множество новых функций, но заметил, что даже мой Galaxy S21 Ultra подлагивал во время игры. FPS был ровным, но иногда мне казалось, что он падает с 60 до 30.

Я взял очень старую Нокию 6.1 с андроидом, запустил свою игру и был в шоке. Это был полный трэш! FPS колебался в диапазоне от 1 до 15. Играть не возможно.

TLDR Что было не так

  • Слои ландшафта

  • Слишком много тяжелой логики в MonoBehaviour:Update

  • Вызовы Instantiate

  • Вызовы Destroy

Как я искал узкие места

Конечно, я сразу же запустил профайлер и начал искать, что заставляло так тормозить мою Nokia 6.1/Galaxy Note 8.

Вы можете видеть, что игра выдавала максимум 30 FPS, но зачастую и того меньше.

Кроме того, когда мне нужно было показать требования к строительству/производству с помощью 3D-моделей ресурсов:

скорость резко падала до 40-60 мс на кадр - узким местом была моя логика OnTriggerEnter (подробнее об этом позже). Также обратите внимание на синие тайминги, которые появляются, когда на экране отображаются новые ресурсы. С моим кодом определенно было что-то не так.

Первый подозреваемый — тени?

Сначала я думал, что все дело в тенях. Я отключил их... и ничего не изменилось. Игра также тормозила.

Второй подозреваемый — настройки качества?

Я пытался запустить ее на низких/очень низких настройках. Стало лучше, но все же 15-30 FPS для такой простой игры — ну нет!

Разделяй и властвуй

Я решил использовать научный подход «разделяй, властвуй и гадай, что не так». Что-то в сцене определенно нагружало GPU (поскольку 80% моего процессорного времени было потрачено на ожидание результатов GPU).

Удаление ландшафта

Начал я с самого большого ассета: я удалил слой Terrain (мой ландшафт).

БУМ! Стабильные 60 кадров в секунду на Galaxy Note 8! Ха-ха! Вот оно:

Я вернул все обратно — снова 15-30... Определенно ландшафт вызвал у меня проблемы с производительностью.

Как исправить ландшафт на мобильных устройствах

Итак, я прочитал официальную документацию по TerrainLayer и заметил следующее:

вы можете использовать четыре слоя Terrain на проход текстуры, без ограничения на количество проходов.

Это означает, что хоть вам разрешено использовать столько слоев Terrain, сколько вы хотите, каждый проход увеличивает время затрачиваемое на рендеринг ландшафта.

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

А у меня было около 8 слоев, смешанных с разными альфа-каналами и масками!

И действительно, когда я сделал 4 слоя, как на этом скрине:

Игра стала очень выдавать очень плавную картинку даже на древнем Android на Nokia 6.1:

Как только я добавляю еще один слой (даже не используя его для рисования!), то производительность сразу падает.

Результат для Terrain

Не делайте более 4 слоев ландшафта, иначе Unity будет очень сильно тормозить на их обработке.

Всплески в MonoBehaviour:Update

А это было легко исправить. Оказалось, что я использовал DateTime.now, чтобы получить текущее время для обработки таймеров задач в игре. Похоже, что его использование может быть не так оптимально на мобильных телефонах, поэтому я переписал логику с использованием Time.deltaTime, чтобы проверить, сколько времени прошло с момента запуска задачи Upgrade/Production:

void Update()
{
    if (actionStarted)
    {
        elapsedActionTime += Time.deltaTime;
        if (elapsedActionTime > actionDuration)
        {
            actionStarted = false;
            elapsedActionTime = 0.0f;
            finalizeAction();
        }
    }
}

Советую вам посмотреть это замечательное видео о том, как реализовать таймеры в Unity:

После исправления обратите внимание, что синие тайминги стали намного короче!

Избавьтесь от Instantiate и Destroy

Когда мне нужно показать материалы для сборки/производства, я интсанцировал префабы и визуализировал их на экране. Затем, когда игрока не было рядом со зданием, я их уничтожил.

Оказывается... Instantiate и Destroy — ОЧЕНЬ ресурсоемкие процедуры.

Видите эти всплески? Это вызовы Instantiate/Destroy. Некоторые из них занимают 40-70 мс:

Я знал, как исправить это с помощью пулинга объектов: пулинг объектов (подробно) — Шаблоны игрового программирования в Unity и C# — Джейсон Вейманн

Я заново реализовал логику для заблаговременного создания всех объектов, когда загружается сцена. А затем просто вытаскивал их из пула объектов и размещал там, где нужно.

Посмотрим на тот же сценарий игры, чтобы отобразить новые объекты ресурсов на экране, но теперь с пулингом объектов:

Заключение

  • Не используйте более 4 слоев ландшафта

  • Не используйте Instantiate/Destroy слишком часто.

  • Используйте объединение пулы объектов, где это возможно

  • Не выполняйте тяжелые задачи в Update

Моя игра теперь выдает 60 FPS на Samsung S21 Ultra и 30-40 FPS на Galaxy Note 8 и Nokia 6.1.

Наконец-то я могу продолжить добавлять новые здания в игру :)

Это моя игра на Nokia 6.1: https://twitter.com/DmytroGladkyi/status/1481540410098991104

Узнать больше и скачать мою старую игру Sloboda можно здесь: Loca Deserta: Sloboda

Вы также можете присоединиться к моему Telegram-каналу: https://t.me/locadesertachumaki. Или https://t.me/locadesertachumaki/467.


Скоро в OTUS пройдет открытое занятие «Проектирование игровых систем», на котором участники научатся проектировать архитектуру игры, а также узнают, из каких компонентов и событий состоит игровая система, и как написать ее таким образом, чтобы это было гибко и масштабируемо. Регистрация для всех заинтересованных по ссылке.

Источник: https://habr.com/ru/company/otus/blog/655095/


Интересные статьи

Интересные статьи

Привет, Habr! Я уже рассказывал про AIOps и методы машинного обучения в работе с ИТ-инцидентами, про зонтичный мониторинг и различные подходы к сервис менеджменту. Сейчас...
Criteo — это компания, работа которой основана на данных. Каждый день через наши системы проходят десятки терабайт новых данных для обучения моделей рекомендаций, обрабатывающих запр...
Один из ключевых сценариев работы в CRM это общение с клиентом в удобном для него канале. По почте, по телефону, по SMS или в мессенджере. Особенно выделяется WhatsApp — интеграцию с ...
Статические веб-сайты — это, уже довольно давно, горячая тема. Они быстры, они чрезвычайно безопасны, так как в них нет CMS, которые можно взломать. Правда, после того, как некто созд...
Но если для интернет-магазина, разработанного 3–4 года назад «современные» ошибки вполне простительны потому что перед разработчиками «в те далекие времена» не стояло таких задач, то в магазинах, сдел...