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

Наша команда по интегрированному успеху поддерживает клиентов Unity в решении их сложных технических проблем. Мы встретились с этой командой старших инженеров-программистов и попросили их поделиться своим опытом в оптимизации мобильных игр.
Наша команда Unity Studio Productions знает исходный код наизусть и работает с множеством клиентов Unity, чтобы помочь им максимально использовать движок. В своей работе они глубоко погружаются в проекты создателей, чтобы помочь выявить точки, где производительность может быть оптимизирована для большей скорости, стабильности и эффективности.
Когда наши инженеры начали делиться своим мнением по оптимизации мобильных игр, мы довольно быстро поняли, что информации слишком много для одного запланированного блога. Вместо этого мы решили превратить их гору знаний в полноценную электронную книгу (которую вы можете скачать здесь), а также в серию блогов, которые освещают некоторые из этих более чем 75 практических советов.
В этом втором выпуске этой серии мы сосредоточимся на том, как улучшить производительность с помощью настроек UI, физики и аудио. Если вы пропустили это, ознакомьтесь с нашим предыдущим постом о профилировании, памяти и архитектуре кода – и следите за нашим следующим, посвященным активам, конфигурации проекта и графике.
Хотите все сразу? Скачайте бесплатную электронную книгу.
Давайте перейдем к делу!
Встроенная физика Unity (Nvidia PhysX) может быть затратной на мобильных устройствах, но следующие советы могут помочь вам получить больше кадров в секунду.
В PlayerSettings проверьте Prebake Collision Meshes всякий раз, когда это возможно.

Убедитесь, что вы редактируете свои настройки физики (Настройки проекта > Физика) и упрощаете свою матрицу столкновений слоев где это возможно.
Отключите Авто синхронизацию трансформаций и включите Повторное использование коллизий.


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

Используйте методы класса, такие как MovePosition или AddForce, чтобы перемещать ваши Rigidbody объекты. Прямое изменение их Transform компонентов может привести к перерасчетам в физическом мире, что дорого в сложных сценах. Перемещайте физические тела в FixedUpdate, а не в Update.
По умолчанию Fixed Timestep в настройках проекта составляет 0.02 (50 Гц). Измените это значение, чтобы оно соответствовало вашей целевой частоте кадров (например, 0.03 для 30 fps).
Если ваша частота кадров падает во время выполнения, это означает, что Unity будет вызывать FixedUpdate несколько раз за кадр и потенциально создаст проблему с производительностью ЦП для контента с высокой физикой.
Maximum Allowed Timestep ограничивает, сколько времени могут использовать расчеты физики и события FixedUpdate в случае падения частоты кадров. Снижение этого значения означает, что во время задержки производительности физика и анимация могут замедляться, одновременно уменьшая их влияние на частоту кадров.

Используйте окно отладки физики (Window > Analysis > Physics Debugger), чтобы помочь устранить любые проблемы с коллайдерами или несоответствия. Это показывает индикатор с цветовой кодировкой объектов игры, которые могут сталкиваться друг с другом.

Для получения дополнительной информации смотрите Визуализация отладки физики в документации Unity.
Unity UI (UGUI) может часто быть источником проблем с производительностью. Компонент Canvas генерирует и обновляет сетки для элементов UI и выдает команды отрисовки на GPU. Его работа может быть затратной, поэтому имейте в виду следующие факторы при работе с UGUI.
Если у вас есть один большой Canvas с тысячами элементов, обновление одного элемента UI заставляет весь Canvas обновляться, что может потенциально вызвать всплеск нагрузки на ЦП.
Воспользуйтесь возможностью UGUI поддерживать несколько Canvas. Разделите элементы UI в зависимости от того, как часто их нужно обновлять. Держите статические элементы UI на отдельном Canvas, а динамические элементы, которые обновляются одновременно, на меньших под-канвасах.
Убедитесь, что все элементы UI в каждом Canvas имеют одинаковое значение Z, материалы и текстуры.
У вас могут быть элементы UI, которые появляются только время от времени в игре (например, индикатор здоровья, который появляется, когда персонаж получает урон). Если ваш невидимый элемент UI активен, он все равно может использовать команды отрисовки. Явно отключайте любые невидимые компоненты UI и повторно включайте их по мере необходимости.
Если вам нужно только отключить видимость Canvas, отключите компонент Canvas, а не GameObject. Это может сэкономить на перестройке сеток и вершин.
События ввода, такие как касания на экране или клики, требуют компонента GraphicRaycaster. Это просто проходит через каждую точку ввода на экране и проверяет, находится ли она в RectTransform интерфейса пользователя.
Удалите стандартный GraphicRaycaster из верхнего Canvas в иерархии. Вместо этого добавьте GraphicRaycaster исключительно к отдельным элементам, которые должны взаимодействовать (кнопки, прокрутки и так далее).

Также отключите Raycast Target на всех текстах и изображениях интерфейса пользователя, которым это не нужно. Если интерфейс пользователя сложный с множеством элементов, все эти небольшие изменения могут снизить ненужные вычисления.

Группы макетов обновляются неэффективно, поэтому используйте их экономно. Избегайте их полностью, если ваш контент не динамичен, и используйте якоря для пропорциональных макетов вместо этого. В противном случае создайте пользовательский код, чтобы отключить компоненты Layout Group после их настройки интерфейса пользователя.
Если вам действительно нужно использовать группы макетов (горизонтальные, вертикальные, сеточные) для ваших динамических элементов, избегайте их вложения для повышения производительности.

Большие представления списков и сеток дорогие. Если вам нужно создать большое представление списка или сетки (например, экран инвентаря с сотнями предметов), рассмотрите возможность повторного использования меньшего пула элементов интерфейса пользователя, а не создания элемента интерфейса для каждого предмета. Посмотрите на этот образец GitHub проекта, чтобы увидеть это в действии.
Наложение множества элементов интерфейса (например, карточек, сложенных в карточной игре) создает избыточную отрисовку. Настройте свой код, чтобы объединить наложенные элементы во время выполнения в меньшее количество элементов и партий.
С учетом того, что мобильные устройства теперь используют очень разные разрешения и размеры экранов, создайте альтернативные версии интерфейса, чтобы обеспечить лучший опыт на каждом устройстве.
Используйте симулятор устройства, чтобы предварительно просмотреть интерфейс на широком диапазоне поддерживаемых устройств. Вы также можете создать виртуальные устройства в XCode и Android Studio.

Если ваш экран паузы или стартовый экран закрывает все остальное в сцене, отключите камеру, которая отображает 3D-сцену. Аналогично, отключите любые элементы Canvas фона, скрытые за верхним Canvas.
Рассмотрите возможность снижения Application.targetFrameRate во время полноэкранного интерфейса, так как вам не нужно обновлять на 60 fps.
Оставляя поле Event или Render Camera пустым, вы заставляете Unity заполнить Camera.main, что неоправданно дорого.
Рассмотрите возможность использования Screen Space – Overlay для вашего Canvas RenderMode, если это возможно, так как это не требует камеры.

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

Если вы используете какой-либо сжатый формат (например, MP3 или Vorbis), Unity будет его декомпрессировать, а затем повторно сжимать во время сборки. Это приводит к двум потерям качества, ухудшая финальное качество.
Уменьшите размер ваших клипов и использование памяти с помощью сжатия:
- Используйте Vorbis для большинства звуков (или MP3 для звуков, не предназначенных для зацикливания).
- Используйте ADPCM для коротких, часто используемых звуков (например, шаги, выстрелы). Это уменьшает файлы по сравнению с несжатыми PCM, но быстро декодируется во время воспроизведения.
Звуковые эффекты на мобильных устройствах должны быть не более 22,050 Гц. Использование более низких настроек обычно имеет минимальное влияние на финальное качество; используйте свои уши для оценки.
Настройка варьируется в зависимости от размера клипа.
- Малые клипы (< 200 кб) должны Декомпрессироваться при загрузке. Это требует затрат ЦП и памяти для декомпрессии звука в необработанные 16-битные PCM аудоданные, поэтому это желательно только для коротких звуков.
- Средние клипы (>= 200 кб) должны оставаться Сжатыми в памяти.
- Большие файлы (фоновая музыка) должны быть установлены на Потоковая передача, иначе весь актив будет загружен в память сразу.
При реализации кнопки отключения звука не просто устанавливайте громкость на 0. Вы можете Уничтожить компонент AudioSource, чтобы выгрузить его из памяти, при условии, что игроку не нужно часто включать и выключать его.
В следующем блоге мы подробно рассмотрим графику и ресурсы. Но если вы хотите получить доступ к полному списку советов и хитростей от команды сегодня, наша полная электронная книга доступна здесь.

Если вы хотите узнать больше о службах интегрированной поддержки и хотите предоставить вашей команде прямой доступ к инженерам, экспертным советам и рекомендациям по лучшим практикам для ваших проектов, тогда ознакомьтесь с планами успеха Unity здесь.
Мы хотим помочь вам сделать ваши приложения Unity максимально производительными, поэтому, если есть какие-либо темы оптимизации, о которых вы хотели бы узнать больше, пожалуйста, дайте нам знать в комментариях.
