Unity грузит процессор на 100
Почему, когда мы строим игровую сцену с unity3d, она использует 100% CPU ?!
Я имею в виду, что речь не идет о сцене со множеством объектов и вещей или пустой сцене, в обоих случаях загрузка процессора составляет 100%.
Как я могу уменьшить это?
Причина, по которой я хочу уменьшить загрузку процессора: Я хочу запустить несколько exe на выделенном сервере для многопользовательской игры, которую я сделал с unity UNET , и в этих сценах у меня ничего нет, кроме некоторых функций и syncvars , даже если у меня нет обновлений функция . Я просто хочу, чтобы эти exe файлы использовали меньше ресурсов ЦП для лучшей работы и повышения производительности.
Можно ли снизить нагрузку на процессор?
Я нашел решение. Это просто из-за того, что я не был предустановлен targetframerate в моих сценариях .
Если мы не установим его, то игра будет пытаться работать с максимально возможной частотой кадров, а если мы запустим ее в пакетном режиме, то она будет занимать все использование процессора.
Недостаточно данных, чтобы помочь вам определить причину проблемы, и она может быть вызвана множеством причин. Попробуйте использовать профилировщик Unity, чтобы отследить, что делает ваш процессор всплеском
Профилировщик Unity
Начните с использования профилировщика единства. Это встроенный инструмент от Unity, который позволяет вам проверить, какая часть приложения использует какой ресурс, его интенсивность и продолжительность его использования.
Если вы перейдете в окно> Профилировщик, вы увидите «Загрузка ЦП», разделенную на более мелкие подкатегории и график для визуализации использования ЦП. Вы можете щелкнуть в любом месте графика, чтобы получить общее представление обо всех процессорах процессора в этом кадре.
Обзорный экран показывает много информации, первые из которых вы захотите посмотреть на «общее» и «время мс». Total - общее количество процессоров, используемых в процентах. Время - это время, которое заняло миллисекунды.
Используйте эти данные, чтобы найти, какой скрипт / действие занимает весь ваш процессор, и начать оптимизацию оттуда.
При запуске сцены в Unity объекты отображаются только тогда, когда они видны в камере. Unity автоматически уменьшает потребности своего ЦП при рендеринге сцены. Конечно, есть некоторые исключения, но Unity достаточно умен, чтобы уменьшить ненужное использование процессора. Ваша проблема здесь может быть связана с несколькими факторами, и каждый фактор имеет свое решение. Универсального нет. Например, это может быть из-за того, что у вас есть несколько игровых объектов с огромными текстурами, или что вы визуализируете сцену с помощью пакета постобработки (который потребляет память / процессор). Или, возможно, ваш компьютер просто недостаточно мощный, и у вашей целевой аудитории такой проблемы не будет
Чтобы добавить к предыдущим великим ответам. Использование графического процессора может повысить производительность и снизить нагрузку на процессор.
Перезагрузить компьютер .
100% загрузка ЦП (i5-9400) Пустая сцена в пустом 2D-проекте.
Возможно, у вас много статических объектов. Для меня это был статичный террарианец, но после снятия флажка статики все стало нормально.
Об использовании процессора. Может случиться так, что единственный процесс, который вы запускаете, это Unity Scene, поэтому ПК использует 100% ЦП для Unity, поскольку ему не нужно выделять ресурсы для других «тяжелых» приложений (я думаю, не 100%, так как другие необходимый процесс для Системы также должен быть запущен). Я думаю, если вы запустите две сцены, это будет около 50% для каждой .
Кроме того, чтобы сделать вашу сцену более эффективной, вы можете попробовать это, чтобы сделать вашу игру более эффективной. Могут быть еще некоторые, и вы не можете применять их все. Но вы можете принять их во внимание как отправную точку:
1- Статическое дозирование
Возможно, в вашей сцене тонна статической геометрии, например, стены, стулья, освещение и сетки, которые никогда не двигаются. Отметьте их как статические в редакторе. Обязательно пометьте их как статические карты освещения, чтобы получить запеченные текстуры карты освещения. Вместо того, чтобы вызывать отрисовку для каждого отдельного объекта, объекты, помеченные как статические, могут быть объединены в одну объединенную сетку. Статическое дозирование имеет одно важное требование: все объекты должны использовать один и тот же материал. Если у вас есть статичные стены из древесного материала и статические стулья из стального материала, стены будут объединены в один чертежный вызов с одной объединенной сеткой, а стулья - в отдельный вызовный вызов с их собственной отдельной сеткой.
2 - наложение текстур
Как отмечалось ранее, каждый материал подвергается розыгрышу. Можно предположить, что для деревянной двери и стального стула могут потребоваться отдельные материалы, поскольку они используют разные текстуры. Однако, если они могут использовать один и тот же шейдер, вы можете использовать атласы текстур для создания одного материала, который могут использовать оба объекта. Текстурный атлас - это просто большая текстура, которая включает в себя все меньшие текстуры. Вместо десятков материалов, загружающих десятки текстур, вы можете использовать один материал, загружающий только одну текстуру. Каждый объект может быть отображен для использования текстуры по разным координатам в атласе. Вы можете сделать это вручную в своем конвейере, но я считаю, что Pro Draw Optimizer Call Хуана Себастьяна весьма полезен. Он автоматически генерирует текстурные атласы и заменяет новые объекты, не мешая вашим ресурсам.
3- Динамическое дозирование
Движущиеся нестатические объекты могут быть динамически объединены в один вызов отрисовки. Я заметил, что это сильно загружает процессор и рассчитывается для каждого кадра, но это хорошая оптимизация. Это работает только на объектах с менее чем 900 вершинами, которые используют один и тот же материал. Используйте наложение текстуры для создания единого материала для ваших динамических объектов, и вы получите дешевое динамическое пакетирование!
4- LODs
Группы LOD - это дешевый способ улучшить производительность. Используйте ресурсы с несколькими LOD и визуализируйте геометрию с меньшей детализацией для объектов, удаленных от камеры. Unity может автоматически исчезать между каждым LOD, когда камера приближается.
5 - заполнять, перерисовывать и отбирать
Это касается темы, с которой я не слишком знаком, но на которую стоит обратить внимание: уменьшение перерисовки, при которой самые дальние объекты сначала рисуются в пикселе, а затем перерисовывают пиксель с каждым более близким объектом сверху. Это не было большой проблемой для вашего среднего дисплея ПК с разрешением 1080p, но это серьезная проблема с VR и мобильными устройствами, которые имеют дисплеи сверхвысокого разрешения. Большое количество оверрейдов в сочетании с большим количеством пикселей убивает вашу скорость заполнения. Фильтрат текстуры является одним из ключевых ограничивающих показателей в графических процессорах. Некоторые решения поставляются из коробки с окклюзионным отбором и отбором усеченного конуса. Отбор Frustum не отображает объекты, находящиеся вне области Frustum камеры. Нет смысла рендерить объекты, которые вы не видите! Отбор окклюзии избавляет от объектов, которые закрыты другими объектами перед ним. Например, комнаты за дверью могут быть полностью исключены. По умолчанию работает выборка окклюзии, которая работает на всей вашей сцене, но правильный дизайн уровней позволит вам отключить все уровни вашей игры.
Группы LOD также могут отбирать объекты, которые находятся слишком далеко от сцены, что еще больше помогает минимизировать скорость заполнения.
6- Дизайн уровней
Если ваша игра включает в себя игрока, путешествующего из комнаты в комнату, наивное решение включает всю игру на одном уровне. Недостатком, однако, является потребление памяти. Каждый объект и материал в каждой комнате загружаются в память, даже если они не видны. Разместите каждую комнату на отдельном уровне и асинхронно загрузите их в коде.
7- Асинхронная загрузка
Прежде чем игрок приблизится к двери в следующую комнату, загрузите следующий уровень. Не загружайте это синхронно, используя Application.LoadLevel (), так как это приведет к зависанию вашей игры во время загрузки. Поскольку отслеживание головы на мгновение захватывает, это вызовет тошноту и ужасный опыт для игрока.
Вместо этого используйте Application.LoadLevelAsync (). Вы можете найти пример этого в примере BlockSplosion Oculus Mobile SDK, в StartupSample.cs
Выключите тени в реальном времени! Объекты, которые получают динамическое затенение, не будут объединены, и вы будете подвергнуты суровому штрафу за вызов при дро.
На ПК вы можете использовать один направленный источник света в реальном времени для создания хороших динамических теней. Большинство современных ПК могут обеспечить великолепное затенение на пиксель. Однако на мобильном устройстве вы хотите придерживаться запеченного освещения, а не тени в реальном времени. Испеки свое освещение с Hard и Soft затенением в очень высоком разрешении.
9- Тени
Специально для эффективной работы с мобильными устройствами вернитесь к старым трюкам с тенями на трехмерных объектах. Полуреалистичные тени можно смоделировать с помощью простого четырехмерного квадрата под вашим объектом с размытой текстурой теней.
10- световые пробники
Когда вы используете запеченное освещение, ваши динамические объекты выглядят неуместно, в то время как статические объекты выглядят великолепно. Вы можете использовать световые зонды для дешевого моделирования динамического освещения на ваших динамических объектах.
Пробники света представляют собой запеченные кубические карты, которые хранят информацию о прямом, непрямом и даже излучающем свете в различных точках вашей сцены. Когда динамический объект движется, он интерполирует образцы соседних зондов света, чтобы приблизить освещение в этой конкретной позиции. Это дешевый способ симуляции реалистичного освещения на динамических объектах без использования дорогих источников света в реальном времени.
11- Избегайте прозрачных и многокомпонентных объектов .
Такие объекты, как стеклянные прозрачные окна, в которых используются прозрачные шейдеры, очень дороги. Существует распространенная практика добавления реализма к стенам с использованием прозрачного материала с текстурой пыли или ржавчины вместе с отдельным базовым диффузным материалом. Это многокомпонентное альфа-смешивание является дорогостоящим; каждый материал добавляет колл-розыгрыш! Обратите внимание, однако, несколько текстур не являются проблемой; Использование нескольких отдельных материалов стоит дорого. Используйте один материал и шейдер, который может смешивать несколько текстур с альфа-смешиванием вместо нескольких отдельных материалов.
12 - Рендереры с сетчатой сеткой
Рендереры сетчатых сеток обычно используются на персонажах с анимированными оснастками, позволяющими реалистично деформировать сетку с помощью физики (тела тряпичных кукол) или пользовательских анимаций (прогулки, прыжки и т. Д.).
Печальная новость: рендеры с сетчатой сеткой не сгруппированы. Каждый персонаж в вашей сцене может создать несколько вызовов для каждого глаза. Я не уверен, как решить это еще.
Оптимизация игр — отдельная головная боль разработчиков, процесс, который может идти бесконечно. Нужно учесть загрузку процессора, видеокарты и не потерять FPS. Нашли статью, автор которой 13 лет разрабатывает на Unity и делится советами по оптимизации. Под катом есть пошаговый план, как сделать проект на Unity более производительным.
Оптимизацию невозможно полностью описать в одной статье. Поэтому сосредоточимся исключительно на методе анализа, который подскажет правильные пути оптимизации вашей конкретной игры.
Заключение
Надеюсь, эта статья поможет вам с оптимизацией или хотя бы подскажет, как выбрать более эффективный подход к профилированию. Удачи с разработкой.
Когда мы делаем игры, мы часто не уделяем должного внимания одному из самых важных аспектов разработки игры — оптимизации. В результате мы получаем лаги и низкий FPS (иногда даже на High-end устройствах, если все совсем уж запущенно). Большинство людей всегда будет рассматривать оптимизацию игры как последний этап, и именно это является первой ошибкой — она всегда должна быть первым пунктом в списке.
Невозможно переоценить привычку при каждой сборке, каждый день, когда вы добавляете новую механику или новую настройку освещения, или какие угодно системы, основанные на физике, в вашу игры, всегда проверять билд, не возникли ли какие-либо проблемы с производительностью из-за этих изменений — это хорошая практика разработки игр.
Если вы не потратите время на оптимизацию производительности с самого начала работы над проектом, на финальном этапе это может вылиться в проблемы для вас и вашей игры. Здесь я хочу поделиться некоторыми мыслями и советами о том, как вы можете повысить производительность вашей игры, основываясь на нескольких практических выводах, которые я извлек из своих ошибок за последние 5 лет.
Запекайте ваше освещение
Грубо говоря, есть три режима освещения: Realtime, Baked и Mixed.
Realtime самый лучший, НО за него приходится платить производительностью. Он вносит прямой свет в сцену и обновляет каждый кадр, когда источники света и игровые объекты перемещаются внутри сцены, обновляя освещение немедленно.
Всякий раз, когда у вас есть возможность запечь (bake) освещение на сцене, обязательно используйте ее, потому что это идеальный вариант для повышения производительности, особенно если вы ориентируетесь на мобильные устройства. Всегда лучше использовать небольшое освещение на сцене, чтобы добиться желаемого вида.
Таким образом, все ваши источники света будут предварительно вычисляться в автономном режиме в процессе под названием Lightmap Baking (запекание). Когда вы устанавливаете GameObject Lightmap Static Flag, Unity запекает информацию о GameObject Light, тенях, отраженном свете и мягких тенях в текстурах, которые касаются вашей сцены. Однако Lightmaps имеет некоторые ограничения, освещение не может обновляться динамически для выбранных вами объектов с Lightmap Static Flag.
Несколько месяцев назад в свободное время я сделал SCIFI сцену, и я думаю, что это лучший пример, показывающий, как работает запеченное освещение. Конечно, я использовал Emission.
Если кого-то интересует обзор создания этой SCIFI сцены, и как я добился этого вида, дайте мне знать, может быть, я мог бы посвятить этому отдельную статью.
Вот видео, если вам интересно!
Поменяем видеокарту
До сих пор работала GTX 460. В этом тесте я заменю ее на GT 210. Кто не знает, это самое днище среди видеокарт. Хуже ее может быть только ее отсутствие.
Импорт проекта для E5 1660:
Результат 5:38. Как и ожидалось, скорость операции не изменилась (разницу спишем на погрешность и сторонние факторы, например, работу Windows).
Используйте отсечения
Это очень хороший способ повысить производительность вашей игры с помощью окклюзии Unity. В целом Occlusion Culling подразумевает, что Unity не будет отображать GameObject-ы, которые полностью скрыты с точки зрения камеры (окклюдированны) другими GameObject-ами.
Чтобы открыть окно Occlusion перейдите в Window->Rendering->Occlusion Culling
По умолчанию Unity применяет Frustum Culling, что означает, что он отображает только линию обзора камеры, показывая все объекты. Например, если камера смотрит на стену, все объекты за этой стеной также будут визуализированы. Нам это совсем не нужно, поэтому следует добавить в нашу сцену Occlusion Culling.
Вот почему мы должны использовать Occlusion Culling, что означает, что камера будет отображать только стену без объектов за ней.
Выводы
1. Для комфортной разработки нужна и высокая тактовая частота процессора, и большое количество потоков. 4-х потоков у процессоров Intel i5 явно недостаточно. Исходя из бюджета, можно рассмотреть 4-х ядерный i7 7700K, который очень любят геймеры или 6-ядерный i5 8600K, оба стоят в районе 250-300$. Если есть деньги, то можно взять и 6-ядерный i7 8700K, который стоит под 400$. Ryzen 5 1600X и Ryzen 7 1800X могут быть адекватной альтернативой за меньшие деньги, хотя и будут проигрывать Intel в максимальной частоте — 4 Ghz против 5 Ghz у Intel (в разгоне, конечно же). Использовать устаревшие платформы Sandy Bridge+, будь то i5, i7 или серверные Xeon 16XX и 26ХХ, имеет смысл только при ограниченном бюджете.
2. Вам не обязательно нужна самая крутая видеокарта. Особенно, если вы делаете мобильные игры. Так что оставьте топовые видеокарты майнерам. Я для замены своей GTX 460 выбрал GTX 1050 за 130$, чтобы Dark Souls 2 пройти еще разок.
3. Кроме того, рекомендую использовать SSD, поскольку Unity активно работает с файлами. Если вы ограничены в бюджете, можно взять даже самый дешевый SSD на 8 или 16 Gb, чтобы хранить на нем сам проект, а также установить туда Unity и все необходимые SDK.
Есть ли смысл загонять объекты в свой список, и оттуда вызывать FixedUpdate - т.е. будет ли это быстрее вызова из юнити - если таких вызовов много?
Так же - в профайлере Physics.UpdateBodies кушает достаточно много время, если ли смысл выключать коллайдеры ручками на расстоянии ? ( в буллете раньше мы так делали C++)
Выглядит так будто слишком много всего рендерится и слишком много физики.
Сегментируй данные, разделяй их обработку порционно, даже можно сделать не на каждый кадр. Не знаю какие алгоритмы ты используешь но например, поиск путей вообще нет смысла пересчитывать по клику или для каждого объекта для одной и той же цели. То есть многие результаты расчетов могут использовать для различных задач. Тем самым используя уже посчитанные данные в одном случае можно применить их результат на разных этапах к другим. В итоге можно разгрузить CPU раз в 100-1000, а может и все 100%. Большинство объектов можно действительно не удалять, а преобразовывать их в нужный объект или хранить про запас, тем самым разгрузить GerbageCollector. Для "Physics" есть еще один прием помимо выключения коллайдеров, это сегментировать область их действий - разделять пространство на слои, тогда автомат быстрее сообразит что с чем столкнется. Для Rendering больше всего проблем с анимированными моделями, так же сократить количество обновлений, или отказаться от Skin модификаторов. Только трансформационная анимация отдельных объектов/елементов. Ну и конечно же не забывать о простых шейдерах и общих текстурных атласах заменяющих расчеты в них. В общем все сводиться к более жесткому определению и выделению статических данных.
FDsagizi
> Есть ли смысл загонять объекты в свой список, и оттуда вызывать FixedUpdate -
> т.е. будет ли это быстрее вызова из юнити
Есть смысл обрабатывать дочерние объекты в родительском FixedUpdate. Не создавая ни каких списков и не вызывая на каждый Child свой FixedUpdate. Также не загружать большое количество объектов компонентами, а использовать всего на одном родительском. Очень большой профит будет от оптимизации полученного цикла в родительском обработчике - в конечном итоге это будет замена на векторную обработку, фиксированного количества дочерних объектов (опять же сегментация обработки данных, хранение не используемых объектов про запас).
zlos
> Выглядит так будто слишком много всего рендерится и слишком много физики.
Рендериться да. Физики много но вся спит
foxes
Спасибо!
Проверил - отключение статичной физики и спящих объектов на растонии ничего не меняет - Physics молодец!
Нужны ли другие инструменты
Есть и другие инструменты, которые использовались раньше: от PIX (Xbox) до Intel VTune. Однако современный профайлер Unity предлагает все, что необходимо для внесения наиболее важных изменений. Для некоторых конкретных платформ можно использовать дополнительные инструменты (PIX, XCode, Android Studio и другие), чтобы упростить доступ к информации об устройстве. Но по моему опыту, встроенных инструментов Unity достаточно для выполнения оптимизации.
Выбор процессора
С выходом Ryzen AMD вернулись на рынок процессоров. Поэтому выбор будет стоять между:
- Intel Core i5
- Intel Core i7
- Ryzen 5
- Ryzen 7
- Многоядерные серверные процессоры Xeon прошлых поколений (ибо стоят недорого)
Последний Core i5 — логичная замена моего i5 2500K. За эти 7 лет Intel, не имея никакой конкуренции и следуя своей концепции «Тик-так-так», прокачала свои процессоры в среднем на 50%. Поэтому даже если после покупки нового процессора Unity будет тупить в полтора раза меньше, я буду доволен.
Core i7 — камень для бояр, стоит вдвое больше i5. Нужен ли Hyper Threading за такие деньги? Согласно различным бенчмаркам, Hyper Threading обеспечивает прирост производительности до 30%.
Серверные процессоры Xeon серий 16ХХ и 26ХХ имеют от 6 до 10 ядер (E5 2680 V2). Списанные с китайских серверов, они продаются на AliExpress по цене 100-150$, поэтому рассмотреть их стоит. Особенно, если вы ограничены в бюджете. Из минусов — придется купить китайскую материнку за 100$ и мощный кулер. Из плюсов — дешевая серверная DDR3 (регистровая).
После выхода Ryzen Intel оперативно скорректировал свой бизнес-план и выпустил шестиядерные процессоры. Если вам нужен процессор для игр, то выбирать нужно однозначно Intel. В большинстве игровых тестов даже 4-ядерные процессоры Intel, например i7 7700K, оказываются лучше Ryzen. Кроме того, гонятся до 5 Ghz даже на воздушном охлаждении.
Но у меня другой случай — я делаю игры, а не играю в них. Станут ли мои coffee break вдвое короче при использовании 8 ядер?
Увы, у меня нет возможности купить все эти процессоры, чтобы провести эксперимент. Но под рукой есть i5 2500K и серверный Xeon E5 1660 с шестью ядрами (будем считать его «аналогом» Ryzen 5, т.к. по бенчмаркам они очень близки). Вполне достаточно, чтобы определить, что же лучше для разработки на Unity.
Итак, будем тестировать:
- разогнанный i5 2500K (4С/4T) ~ 80$
- немного разогнанный (на хуанане особо не разгонишь) E5 1660 (6C/12T) ~ 130$
Для сравнения, результаты бенчмарка этих процессоров и более новых, рассматриваемых к покупке (все в разгоне):
Таким образом, выбирая новый процессор, можно использовать эти данные, чтобы оценить выигрыш в быстродействии.
Ускорьте настройку компилятора Il2CPP
Используйте Release или даже Debug, если компиляция кода не занимает слишком много времени.
PlayerSettings.SetIl2CppCompilerConfiguration(group, mode);
Il2CppCompilerConfiguration.Master //Slow build, Quick performance
Il2CppCompilerConfiguration.Release //Medium build time, Good runtime performance
Il2CppCompilerConfiguration.Debug //Quickest build, slowest runtime performance
Общие рекомендации
1. Автоматизируйте билды, чтобы они собирались в один клик.
Пропускайте неважный игровой контент. Например, в отладочных билдах можно скипать видео-заставку. Создайте специальный интерфейс для отладки, который потребуется только на этапе разработки. Например, можно добавить отдельные кнопки, которые будут включать/выключать определенные задачи профилирования. Так отпадет необходимость создавать отдельные билды.
2. Ускорьте билды.
Обеспечьте возможность собирать более быстрые и менее объемные билды (например, с одним уровнем и одной машиной в гоночной игре).
3. Отключите обфускацию, если она используется.
Некорректные данные при включении GPU Profiler
Включение профайлера GPU покажет некорректные результаты для некоторых платформ, поэтому лучше отключить его. VSync будет использовать более 90% ресурсов системы, а такие вещи, как GPUProfiler.EndQueries, будут отображаться некорректно и при этом вызывать огромные нагрузки. Профайлер GPU поможет глубже разобраться в ситуации, но только когда точно знаешь, как он работает и зачем он включен.
Определить кто задерживает исполнение программы — GPU или CPU — можно, используя Timeline профайлера CPU:
Gfx.WaitForPresent: ограничения GPU, CPU ожидает ответа от GPU;
Gfx.WaitForCommands: ограничения CPU, GPU ожидает ответа от CPU.
Оперативная память
У меня 12 Gb RAM, и ее использование при работе с Unity не превышает 50%. Таким образом, для разработки на Unity хватит и 8 Gb RAM. И параллельно еще сможете запустить фотошоп и ютуб.
Когда тупит Unity?
Существует несколько операций, выполнение которых занимает много времени при работе с Unity. Обычно в таких случаях я иду чаевничать или играю с котом. Иногда даже удается пройти пару уроков в Duolingo.
- Обработка файлов проекта. Unity считает хэши всех файлов в проекте, создает мета-файлы и строит свою библиотеку (папка Library). Особенно долго Unity обрабатывает звуковые файлы. Библиотеку никто не хранит в системе контроля версий, поэтому если вы давно не синхронизировали проект, вас ждет пара минут ожидания. Кроме того, если изменить платформу, например с Android на iOS, этот процесс придется повторить.
- Запекание света (baking). Тут все зависит от сложности освещения. Я делаю мобильные игры, поэтому запекание практически не использую.
- Сборка проекта. Во многом зависит от выбранной платформы и самого проекта. WebGL может вообще собираться целую вечность (иногда реально состариться можно и еще борода отрастает). Я имею ввиду именно получение готовой игры, а не компиляцию исходного кода (которая происходит практически мгновенно).
План оптимизации
Каждая задача должна быть выполняемой. Особенно что-то такое пугающее и, казалось бы, бесконечное, как профилирование. Я написал план, следуя которому вы сможете измерить и ощутить прирост производительности игры.
Некорректные данные из-за физики в FixedUpdate
Профилирование само по себе настолько загружает систему, что это может сильно повлиять на некоторые данные. Игра будет идти хуже, а значит, будет выполняться больше физики FixedUpdates. Даже если профайлер покажет, что на физику ушло 33% фреймрейта, по факту в итоговом билде это значение будет ближе к 10%. Так же как в случае с глубоким профилированием, эти некорректные данные могут сподвигнуть разработчиков заниматься оптимизацией не там, где это принесет значимый результат.
«Короче, что лучше?»
Самые нетерпеливые сразу могут промотать в конец)
Удаленное профилирование (Remote profiling)
Чтобы заставить его работать, вам необходимо установить Android SDK и подключить JDK и USB дебаггинг. Помните, что всегда полезно тестировать, как работает ваша игра, когда речь идет о механике, масштабировании пользовательского интерфейса и т. д. Не говоря уже о тестировании реальной производительности в игре вкупе с вышеперечисленным. Чтобы протестировать реальную производительность игры, вам нужно создать специальный билд для профилирования.
Чтобы подключить Remote Profiler, перейдите в меню Edit > Project Settings > Editor и в разделе Device выберите Any Android Device.
Статический батчинг
Статический батчинг (Static Batching) используется всякий раз, когда GameObject-ы статические. Такие статические GameObject-ы не должны перемещаться, масштабироваться или вращаться, а также должны использовать один и тот же материал для всех статических GameObject-ов, чтобы батчинг работал.
Если ваши GameObject-ы не взаимодействует с вашим Player или если вы не меняете Transform, то лучше всего использовать статический батчинг для большинства вариантов среды в вашей игре, таких как здания, дороги и т. д.
Динамический батчинг
Динамический батчинг (Dynamic Batching) похож на статический в том, что для GameObject-ов должны использоваться те же материалы, но может группировать движущиеся объекты без необходимости делать их статическими. По сути, Unity может автоматически загружать GameObject-ы в один и тот же вызов отрисовки, если они используют один и тот же материал, но на них накладываются некоторые ограничения динамической пакетной обработки в соответствии с Unity:
- Пакетная обработка динамических GameObject-ов имеет определенные накладные расходы на каждую вершину, поэтому пакетная обработка применяется только к сеткам, содержащим не более 300 вершин и не более 900 атрибутов вершин.
- Если ваш Shader использует Vertex Position, Normal и один UV, вы можете группировать до 300 вершин, но если ваш Shader использует Vertex Position, Normal, UV0, UV1 и Tangent, то только 180 вершин.
- : ограничение количества атрибутов может измениться в будущем.
- GameObject-ы не обрабатываются пакетно, если они содержит зеркальное отражение в transform (например, GameObject A со скейлом +1 и GameObject B со скейлом –1 не могут быть объединены вместе).
- Использование разных экземпляров Material приводит к тому, что GameObject-ы не объединяется в пакет, даже если они по сути одинаковы. Исключение составляет рендеринг Shadow Caster.
- Игровые объекты с картами освещения имеют дополнительные параметры рендеринга: индекс карты освещения и смещение/скейл в карте освещения. Как правило для пакетной обработки, GameObject-ы с динамической картой освещения должны указывать на одно и то же местоположение карты освещения.
- Multi-pass шейдеры исключают батчинг.
- Почти все шейдеры Unity поддерживают несколько источников света при прямом рендеринге, эффективно выполняя за них дополнительные проходы. Вызовы отрисовки для «дополнительных источников света на пиксель» не группируются.
- У Legacy Deferred (предварительный проход света) пути рендеринга динамический батчинг отключен, потому что он должен отрисовывать GameObject дважды.
- Для каждого совместимого типа рендерера Unity собирает весь батч контент в 1 большой Vertex Buffer.
- Рендерер устанавливает состояние материала для батча.
- Unity связывает Vertex Buffer с Graphics Device.
- Для каждого рендерера в батче Unity обновляет смещение в Vertex Buffer, а затем отправляет новый вызов отрисовки.
Сборка проекта под Android
Снова начинает i5 2500K:
Результат 2:50. Работает на максимальной частоте, а загрузка ядер временами достигает 100%. Будь их больше, результат бы улучшился.
Результат 2:50, абсолютно такой же! Частота все та же — 3600 Mhz, но загрузка ядер ни разу не достигает 100%. Хотя нагрузка определенно выше, чем при импорте проекта.
Выводы можно сделать абсолютно такие же, как в предыдущем тесте. Кроме того, i5 уперся в свой потолок.
Отдельно про ограничение со стороны ЦП
У всех наших игр на Unity ЦП становится узким местом всей системы. Если проблемы с видеокартой и возникают, то обычно из-за того, что мы не провели какую-то базовую оптимизацию. Дело в том, что Unity очень много задач отправляет на один тред ЦП, хотя современные процессоры часто имеют по восемь ядер.
Невозможно использовать всю фактическую мощность CPU. Поэтому такие функции, как Graphic Jobs, очень важны. Burst/Jobs/DOTS должны стать решениями этой проблемы в будущем. Но на сегодняшний день мы еще не нашли способ применить их с пользой для наших игр.
Таск менеджер типичной игры на Unity с задержкой в CPU 3 (основной тред Unity)
Батчинг GameObject-ов
Батчинг (Batching, или пакетная обработка) — очень хороший метод повышения производительности за счет сокращения количества вызовов Draw, который представляет из себя группирование рендеринга нескольких похожих GameObject-ов в одном вызове draw. Существует два типа методов батчинга: статический и динамический. Для батчинга существуют некоторые ограничения — мы не можем выполнять пакетную обработку skinned мешей, ткани и некоторых компонентов рендеринга.
Пересоздание удаленной папки Library
Удаленная папка это не та, которая далеко находится. Я ее просто удаляю, чтобы Unity выполнил повторный импорт проекта (функции Reimport не доверяемся).
Первым в бой идет i5 2500K:
Результат 5:43. Процессор практически все время трудится на максимальной частоте 4700 Mhz, однако на 100% не загружается.
Затем очередь E5 1660:
Результат 5:53. Процессор работает, не напрягаясь, а частота лишь изредка достигает максимума в 4200 Mhz. Средняя загрузка процессора около 12%.
О чем говорят эти результаты? 5 минут в обоих случаях это довольно долго. i5 2500K не сбрасывает максимальную частоту, но при этом не загружен на 100%. E5 1660 старается использовать все ядра, и поэтому снижает частоту до 3600 Mhz (но при этом средняя загрузка очень низкая).
Остается предположить, что первому не хватает потоков, а второму частоты, поэтому оба процессора показывают одинаково плохой результат.
Аврал за несколько дней до дедлайна
Невозможно подтянуть производительность за несколько дней и даже недель до релиза, ведь иногда приходится полностью менять работу определенных систем. Игра не обязательно должна идти с 60 FPS на всех стадиях продакшена. Но не стоит оставлять огромный кусок работы и капитальные пересмотры архитектуры на последнюю неделю.
Тестовый стенд
- Свежеустановленный Windows 10 (не захламленный всяким мусором)
- Самый дешевый китайский SSD
- Видеокарты GT 210 и GTX 460
- Проект Tap Tap Builder (мобильная игра для Android и iOS), суммарный размер ассетов около 500 Mb
Профилируйте свою игру
Профайлер (Profiler) — первый в списке и один из моих самых любимых инструментов в Unity для мониторинга производительности игры с целью узнать, что на самом деле вызывает проблемы с производительностью. Он очень полезен для получения подробного представления о том, как ваша игра реагирует на различные изменения в редакторе.
Вы можете найти Profiler в Window->Analysis->Profiler
Он отображает такие категории, как использование CPU и GPU, рендеринг, физику, аудио и многое другое. Мы не можем полагаться на профилирование в редакторе (Editor Profiling), поскольку редактор влияет на производительность проекта во время тестирования, а это может влиять на достоверность информации профилирования. Для получения точных данных профилирования лучше создавать отдельный билд.
Сложности с сетевым решением
Программисты порой полагают, что сетевое решение (например, Photon) сильно снижает производительность. Они видят, что из-за него происходят пики загрузки ЦП, но забывают заглянуть поглубже в стек вызовов. Сетевой инструмент запускает методы, вызываемые из сети (так называемые RPC), а они — часть вашего собственного кода, которая не имеет к сети никакого отношения. В таких ситуациях нужно оптимизировать RPC-методы и/или распределить их рабочую нагрузку.
Смежные вопросы
Некорректные данные при запуске Deep Profiling
Не используйте эту опцию, пока не узнаете, когда это нужно делать. Deep Profile можно включить, если есть проблема с конкретной частью программы: это поможет определить, какая часть кода вызывается. При этом не стоит ориентироваться на полученные тайминги, потому что глубокое профилирование слишком сильно перегружает небольшие методы, странным образом искажая все результаты. В качестве альтернативы или дополнения к глубокому профилированию можно расставлять собственные маркеры профиля.
Использование кастомных маркеров профиля:
Что оптимизировать
Путей оптимизации очень много, поэтому я и предлагаю метод поиска узких мест, а не четкую последовательность действий. Определив проблемные места, можно вносить изменения, которые важны именно для конкретной игры.
Недостаток производительности GPU: динамическое разрешение
Можете использовать динамическое разрешение как временное решение. У вас может быть скрипт, проверяющий фреймрейты CPU и GPU, и, если графический процессор — узкое место вашей игры, уменьшите разрешение игровых камер (но не пользовательского интерфейса). Как только возьмете этот момент под контроль, сможете оптимизировать нагрузку графического процессора, чтобы она меньше зависела от этой настройки и можно было улучшить визуал.
Пики загрузки CPU
Используйте Incremental Garbage Collection. Благодаря этой функции, возможно, не придется сокращать выделенные сборщики мусора. Часто пиковые загрузки ЦП возникают из-за его работы. Incremental Garbage Collection позволяет значительно уменьшить пики загрузки. Правда, на некоторых проектах нам пришлось отключить эту функцию на нескольких платформах из-за сбоев Unity (Switch — Unity 2019.4).
Недостаток производительности CPU
Прекратите использовать Occlusion Culling по умолчанию. Вроде бы отличный инструмент, но на практике мы улучшаем производительность игры, полностью отключив Occlusion Culling. В каждой выпущенной нами игре на Unity, ЦП в определенный момент становится узким местом всей системы, а Occlusion Culling всегда дополнительно нагружает процессор. Конечно, все зависит от игры, но не забудьте проверить, помогает ли вам эта функция или только замедляет.
GPU и CPU: технология рендеринга
Хотя на топовых платформах в наших играх часто используется Deferred Rendering, было доказано, что лучше переключиться на Forward Rendering на устройствах более низкого уровня (мобильные платформы, Switch, Xbox One, PS4). Преимущества в производительности Deferred становятся очевидными только при использовании многопиксельной подсветки.
Сейчас много говорят про новые технологии рендеринга — HDRP и URP, повышающие производительность. Но на практике мы не слышали, чтобы благодаря им игры выиграли в производительности (скорее, наоборот).
GPU и CPU: отладчик кадров
Необходимо использовать отладчик кадров Unity (Frame Debugger). Подобно Timeline в профайлере, этот инструмент помогает понять, как на самом деле работает ваша игра, визуализируя ее. Обработка вызовов отрисовки отнимает процессорное время. То есть — важно сократить вызовы отрисовки, использовать слияние шейдеров и/или материалов, GPU Instancing, а также динамический и статический батчинг.
Отладчик кадров также помог нам отследить неприятные ошибки, из-за которых объекты или весь экран становились черными. Прокручивая вызовы отрисовки, можно точно узнать, когда и как что-то отображается.
Отладчик кадров Unity
Прочее
Помимо Occlusion Culling есть еще две настройки, которые стоит проверить перед использованием.
Нам пришлось отключить их на многих платформах из-за сбоев Unity (Particle jobs содержат ошибки). Как обычно: перед включением проверьте не страдает ли от этого производительность.
Сотрудники Unity упоминали, он полезен только при работе на старых устройствах. Динамический батчинг тоже может сильно нагружать ЦП, и выгода от видеокарты не окупится. Пока не смог оценить явные плюсы и минусы этой настройки.
Петля оптимизации
Поскольку подготовка билда и сбор данных профилирования отнимает много времени, перед повторной сборкой и проверкой стоит вносить комбинированные изменения с точки зрения базовой производительности, пиков загрузки и так далее.
1. Документирование производительности
Фиксируйте производительность вашей игры, желательно на тех этапах, которые легко воспроизвести. Задокументируйте результаты и сохраните данные профилирования. Стоит записать уровень загрузки CPU (и GPU), чтобы оценить прогресс. Я часто также отслеживаю загрузку памяти, чтобы подготавливать эффективные новые билды и при необходимости сокращать объем используемой памяти.
Можно использовать Profile Analyzer: он упрощает сравнение данных в профиле. Это поможет обнаружить пики загрузки или другие отличия между разными билдами/конфигурациями настроек. То есть этот инструмент отмечает все произведенные улучшения.
Window > Analyse > Profile Analyzer
Profile Analyzer экономит много работы: выберите две области, и он автоматически сообщит, в чем разница.
2. Базовая производительность
Сначала мы обычно игнорируем пики загрузки и сосредотачиваемся на том, чтобы базовая производительность была в пределах нормы. Здесь главное довести «нормальный» игровой цикл до приемлемого уровня, будь то 30 кадров в секунду (мобильные платформы, Switch), 60 или даже 120 (VR).
Используйте профайлер Unity, чтобы понять, что снижает базовую производительность, и решить только самые важные проблемы. Timeline помогает увидеть, как работает игра с точки зрения производительности.
Window > Analysis > Profiler
Режим отображения Timeline куда полезнее, чем Hierarchy. Timeline показывает порядок задач и их зависимость друг от друга. Стоит обратить внимание на следующие моменты:
скрипты/плагины, запускающие тяжелый код в Update, FixedUpdate, LateUpdate и т.д.;
аудио: звук должен давать не больше 5% нагрузки на процессор (убедитесь, что вы не воспроизводите звуки, которые не слышны);
неэффективная реализация пользовательского интерфейса и как следствие перегрузка процессора (избегайте большого количества перерисовок);
запуск анимаций, которые не видны;
оптимизация настроек Physics Fixed Deltatime: не слишком мало (с ошибками в физике) и не слишком много (слишком сильная потеря производительности). Используйте FixedUpdate() только для того кода, который должен работать во время физики, поскольку этот метод сильно сказывается на FPS.
Также было бы неплохо время от времени создавать релизный билд. На нем можно проверить фактический FPS.
3. Пики загрузки
Пики легко идентифицировать, потому что они очевидны. Здесь тоже можно использовать Timeline, чтобы понять, почему какая-то часть кода обрабатывается дольше, чем нужно.
Тестируйте игру на устройстве с медленным жестким диском (не SSD). Не обязательно фиксить все пики, иногда можно распределить их нагрузку. Недавно мы провели очень простую оптимизацию.
Мы вызвали: родной метод Main() платформы; вызов через Monobehaviour Update(); метод (для обновления состояний платформы и ее четырех контроллеров). Это заняло 2,0 мс, что очень много для целевого значения в 16 мс. В итоге удалось оптимизировать процесс примерно до 0,2 мс, распределив его так, чтобы он запускался только на каждый X-й кадр, ведь не было необходимости запускать его на каждый фрейм. А также мы стали обновлять состояние только одного контроллера за один кадр, а не всех четырех сразу. Используя значение Time.frameCount по модулю, можно легко распределить множество различных операций по 16 кадрам в секунду.
4. Повтор
Пересоберите игру с учетом проведенной оптимизации и начните все заново с первого пункта. Сравните полученные результаты с предыдущими и определите, какие проблемы устранять дальше.
Отсутствие плана
Нельзя заниматься профилированием и оптимизацией без плана. Нет смысла работать вслепую и оптимизировать код или арт, не определив узкие места.
Не создавайте рандомные профили в редакторе или на своей рабочей машине, если они не имеют никакого отношения к целевой платформе. Также не стоит перепрыгивать с одной цели профилирования на другую. Нужно сначала определить основные цели, а потому уже решать как повышать производительность игры. Оптимизация станет более отлаженной, если действовать по плану.
Программисты порой оптимизируют отдельные куски кода — например, оптимизируют UI с помощью цикла foreach (с 10 мс до 3 мс). А художники рассчитывают полигоны. И то, и другое — улучшение, но зачастую эти действия не дают заметных результатов. Лучше сосредоточиться на опыте игрока, ведь в конечном итоге — это единственный важный результат.
Рекомендации по платформам
Просмотрите все Player Settings в Unity, чтобы найти полезные настройки. Например, у высокопроизводительной консольной платформы есть уровни сжатия билда, которые можно отключить, чтобы ускорить его работу.
Загрузка Windows 10
- E5 1660 загружает систему за 21 секунду
- i5 2500K загружает систему за 26 секунд
Билд для профилирования
Чтобы убедиться, что Unity имеет доступ к вашему билду, который можно профилировать, вы должны включить “Development build or Deep Profiling Support” и “Auto-connect Profiler” в настройках билда перед его созданием. Это позволяет редактору Unity автоматически подключать ваш билд.
Когда ваша бид будет готов, не закрывая окно Unity Profiler откройте свою игру. Теперь Unity будет автоматически отображать данные о производительности текущего билда игры в окне профайлера.
Узнать о профайлере больше вы можете здесь.
Распространенные ошибки
Начнем с того, чего не стоит делать, чтобы не допустить распространенные ошибки. Конечно, из любого правила есть исключения, но новичкам в оптимизации лучше избегать некоторых вещей.
Сокращение используемых объемов памяти и исправление OOM-сбоев
Работая над производительностью игры, вы столкнетесь со сбоями Out Of Memory или медленной загрузкой из-за неоптимизированного использования ресурсов. Хотя память не обязательно напрямую влияет на производительность, она все-таки важна. Оптимизацию использования памяти лучше всего проводить при подготовке оптимизационных билдов. Используйте Memory Profiler, чтобы точно определять занимаемые объемы. Совет: велика вероятность, что шейдеры съедают 50% памяти, тут стоит глубже погрузиться в правильное ограничение ключевых слов шейдера (на эту тему стоит написать отдельную статью).
Window > Analysis > Memory Profiler
Видеокарта
Видеокарта непосредственно для разработки никакого значения не имеет. Она понадобится вам только для запуска и тестирования проектов. Если вы делаете игру для PC с «крутым графоном», стоит потратиться на хорошую видеокарту. Поскольку я делаю мобильные игры, у меня нет никакой нужды бежать в магазин за GTX 1080 (которую наверняка уже раскупили майнеры). Поэтому я решил оставить свою старушку GTX 460. Тем не менее, я проведу тест с двумя видеокартами.
Тестовая методика
Методикой это назвать можно с натяжкой. Берем секундомер и запускаем следующие операции:
- загрузка Windows 10 (с момента включения блока до появления рабочего стола)
- пересоздание удаленной папки Library (с момента открытия проекта до появления окна редактора)
- сборка игры под Android (с момента нажатия кнопки Build до появления APK)
- Параллельно будем смотреть на загрузку CPU в AIDA64.
Подготовка
1. Возьмите за ориентир самую слабую платформу.
Выберите один конкретный компьютер или платформу для профилирования. В идеале это должно быть самое слабое устройство из тех, на которых будет запускаться ваша игра. Мы часто берем в качестве такого ориентира Xbox One. На этой консоли довольно медленный диск, устаревшие процессор и видеокарта. Nintendo Switch и современные мобильные устройства работают лучше, чем Xbox One.
2. Сделайте так, чтобы вам было удобно.
Важный дополнительный шаг — создать комфортные условия профилирования. Сделайте все возможное, чтобы ускорить подготовку билдов. Их будет много, поэтому эта работа точно принесет пользу и для других задач разработки, например, при поиске и исправлении багов.
Пару слов о моем 2500K
Intel Core i5 2500K вышел в 2011 году и относится к линейке Sandy Bridge (техпроцесс 32 нанометра). Частота 3,30 GHz (3,70 GHz с Turbo Boost), 4 ядра и 4 потока, кэш-память 6 Mb. Ничего особенного, если бы не адекватный ценник и приставка K. На хорошей mobo (у меня чипсет p67) гонится как черт (у всех Sandy Bridge под крышкой припой). У меня он 7 лет проработал на частоте 4.7 Ghz. На дворе 2018 год, а этот процессор до сих пор считается лучшим в бюджетном сегменте, на барахолке он стоит около 5000 рублей. В общем то, никаких особых неудобств при разработке я не испытываю, такого процессора вполне хватает. Почему не i7? Да потому что стоит он вдвое больше, а я денюжкой не сорю)
Читайте также: