Бесплатная консультация
← Все статьи

Как перестать компилировать лишние шейдеры

Shader variants редко становятся проблемой в начале Unity-проекта. Несколько материалов, пара keywords, простые эффекты — сборка проходит быстро, а размер проекта почти не меняется.

Комплектующие игрового компьютера

Shader variants редко становятся проблемой в начале Unity-проекта. Несколько материалов, пара keywords, простые эффекты — сборка проходит быстро, а размер проекта почти не меняется.

Проблема появляется позже. Добавляются новые материалы, quality settings, lighting features, VFX, платформенные различия. Один shader начинает иметь десятки комбинаций параметров, а Unity приходится рассматривать каждую из них как потенциально необходимый вариант.

В результате команда замечает странную картину: gameplay почти не изменился, а build стал собираться значительно дольше. Shader compilation занимает всё большую часть pipeline, растёт размер сборки, а некоторые платформы начинают особенно болезненно реагировать на количество вариантов.

Поэтому контролировать shader variants лучше не тогда, когда CI уже компилирует их десятками тысяч, а в процессе production.

Один keyword может создать гораздо больше вариантов, чем кажется

Каждый shader keyword сам по себе выглядит безобидно. Например, материал может поддерживать normal map, emission, дополнительный эффект и несколько режимов качества.

Но комбинации начинают перемножаться.

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

При этом большая часть комбинаций игре вообще может быть не нужна.

Например, проект никогда не использует конкретный эффект вместе с определённым quality mode, но shader всё равно позволяет такую комбинацию. Если pipeline не умеет её исключить, Unity может продолжать учитывать этот вариант при сборке.

Поэтому проблема shader variants обычно решается не одной настройкой, а пониманием того, какие комбинации действительно существуют в продукте.

Сначала измеряйте, потом удаляйте

Опасно начинать оптимизацию с агрессивного stripping всего, что кажется лишним.

Игровая станция с подсветкой

Если удалить вариант, который используется только в редкой сцене или на конкретном устройстве, проблема может проявиться уже после релиза: материал станет розовым, пропадёт эффект или shader будет выглядеть иначе на определённой конфигурации.

Поэтому работа начинается с анализа.

Какие shaders создают больше всего вариантов? Какие keywords используются фактически? Какие комбинации появляются только теоретически? Какую часть времени сборки занимает shader compilation?

Это хорошо вписывается в общий подход к аудиту Unity-проекта: сначала нужно найти реальные bottlenecks, а уже затем оптимизировать конкретную систему.

Shader stripping должен соответствовать реальному контенту

Unity позволяет исключать ненужные варианты из сборки. Но stripping эффективен только тогда, когда команда понимает структуру проекта.

Видеокарты крупным планом: производительность железа

Например, если определённый rendering feature никогда не используется на мобильной платформе, связанные с ним варианты можно не включать в соответствующий build. Если часть keywords существовала для старой системы, которая уже удалена, их также стоит убрать из shader pipeline.

Особенно полезно регулярно пересматривать shaders после крупных изменений art direction. В проекте могут оставаться материалы, keywords и старые варианты, которые уже никто не использует, но они продолжают увеличивать стоимость сборки.

Здесь shader optimization напрямую связан с узкими местами build pipeline. Если большая часть build time уходит на обработку вариантов, более мощная build machine лишь частично маскирует проблему. Намного выгоднее уменьшить объём работы, которую Unity вообще должна выполнять.

Не забывайте про runtime

Контроль variants нужен не только ради CI.

Большое количество shaders и неправильная стратегия их подготовки могут проявляться уже во время игры: например, через shader compilation или заметные stutters при первом появлении определённого эффекта.

Особенно неприятно, если такой spike возникает в бою или при загрузке новой сцены.

Поэтому важно проверять не только размер build и время компиляции, но и реальные gameplay-сценарии. Если проект ориентирован на мобильные устройства, shader complexity также становится частью общего performance budget.

Красивый материал, который хорошо работает на одном объекте, может стать проблемой, когда десятки таких объектов одновременно появляются в кадре.

Контроль variants должен стать частью pipeline

Разовая чистка помогает, но через несколько месяцев проблема легко возвращается.

Графический ускоритель для игрового компьютера

Новый shader получает дополнительные keywords, подключается новая система освещения, художники начинают использовать ещё один вариант материала — и количество комбинаций снова растёт.

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

В Unity-разработке такие проверки логично связывать с profiling, build pipeline и техническими правилами art production. Тогда shader complexity перестаёт быть скрытой стоимостью, которая постепенно накапливается внутри проекта.

Главная цель здесь не в том, чтобы добиться минимального количества вариантов любой ценой. Нужно оставить те комбинации, которые действительно нужны игре, и убрать те, которые существуют только потому, что pipeline когда-то позволил их создать.

Если Unity-проект начал заметно дольше собираться, shader compilation занимает значительную часть build time или количество variants растёт вместе с каждым обновлением — пришлите описание rendering pipeline и текущего build process. Разберём, какие варианты действительно используются и где можно сократить стоимость сборки без риска сломать материалы в production.

Следующая статьяShot list игрового трейлера без лишних кадров
→