Как стать автором
Обновить

Как сделать билд минимального размера в Unity?

Время на прочтение7 мин
Количество просмотров13K

Всех с Новым Годом! Меня зовут Григорий Дядиченко, и я технический продюсер. Размер билда. Сегодня хотелось бы поговорить о нём и составить некий чек-лист, который полезно проходить перед выкладкой проекта. Если вам интересно, как можно инструментами Unity уменьшить вес сборки — добро пожаловать под кат!

Одна из больших задач в разработке с которой все постоянно сталкиваются — это оптимизация веса билда. В вебе лучше иметь минимальный вес приложения. В мобильных сторах существует ограничение, что билд должен весить не больше 200 мб для скачивания по мобильной сети на IOS и 150 мб для Android в случае апп бандла. Такое ощущение что плевать на размер сборки только разработчикам Call Of Duty, но пусть это будет на их совести. Перед релизом важно пройтись по ассетам в вашем проекте и подрезать что и где можно.

Из чего состоит приложение?

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

  1. Текстуры

  2. 3д модели

  3. Анимации

  4. Звуки

  5. Шейдеры

  6. Код

  7. Код движка

Мы пойдём от простых оптимизаций к сложным. От более эффективных и первоочерёдных, к тем что нужно делать в "самый последний момент". И начнём мы пожалуй с текстур.

Оптимизация текстур — Текстурные Атласы

Текстуры — это общая боль для 2д и для 3д проектов. Поэтому начнём с них. И начнём с самого простого понятия текстурный атлас.

Текстурный атлас — это изображения собирающее в себе другие изображения. По сути берётся большая текстура и через uv-координаты разбивается на зоны, в которых будут лежать другие текстуры. Это самая база, но это важно знать. Текстурные атласы оптимизируют как отрисовку, так и вес билда.

Для 2д и интерфейсов в Unity есть механизм Sprite Atlas. Чтобы атласы заработали, нужно в настройках Project Settings->Editor->Sprite Packer включить Sprite Atlas. Если он не будет включен, то созданные атласы не будут ничего делать.

Чтобы создать атлас в Unity. Нужно в файлах проекта сделать Create->2D->Sprite Atlas. И дальше в поле Objects for Packing положить нужные текстуры (так же можно положить папку).

Важно: чтобы избежать артефактов в UI отключайте настройки Allow Rotation и Tight Packing. Для SpriteRenderer всё с этими настройками будет работать нормально.

В случае 3д игр атласы собираются обычно в 3д софте. Есть ассеты для объединения материалов и формирования атласов для 3д. Но это больше про оптимизацию рендера, чем про оптимизацию веса сборки.

Оптимизация текстур — Настройки Сжатия

Когда атласы настроены можно попробовать их ещё пожать или пожать текстуры. Тут нет конкретного рецепта. Скажем если вы ориентируетесь только на топовые мобильные устройства, то там чаще всего будет работать без проблем сжатие ASTC, даже на андроид. Можно по выбирать разные варианты самого сжатия и настроить их так чтобы найти баланс между весом и артефактами. Например возьмём обложу из одной статьи.

С настройками по умолчанию, да ещё она у нас и NPOT (размеры не степени двойки) она весит 2.6 мб.

Вернувшись к прошлому пункту. Мы засунем её в спрайт атлас. Теперь она весит 2.0 мб, хотя она стала больше. Как так вышло? Раньше она была не компрессированная (так как размер текстуры был не степеней двойки и некоторые алгоритмы компрессии в этом случае не работают), а теперь она с компрессией ETC2. Но мы же хотим увидеть "настоящее сжатие".

И тут уже посмотрим на два скрина. Стоит учитывать что некоторые форматы сжатия не поддерживаются устройствами.

Было: (2мб)

Стало: (230кб)

И вот мы размер нашей текстуры с 2.6 мб снизили до 230кб. Больше чем в 10 раз. Так как это глубокая степень оптимизации важно такие вещи хорошо тестировать.

Важно: не имеет никакого значения сколько файл весит у вас на диске. А то некоторые оптимизируют текстуры внешними утилитами. Это работает только если текстуры идут в билд as-is, скажем через папку StreamingAssets. Но обычно лучше использовать настройки компрессии движка ничего не выдумывая.

Оптимизация текстур — Градиенты

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

В общих чертах градиенты на кнопках и на фонах лучше делать шейдерами. Странно видеть в проекте фон в виде градиента большим спрайтов 2048х2048. Который скажем на андроиде либо идёт без сжатия, либо с артефактами лесенкой. Лучше просто сделать шейдер. По производительности шейдеры тривиальные. Вес приложения будет ниже. Выглядеть будет красивее.

Оптимизация текстур — Подход к интерфейсам

Этот пункт не всегда возможен. Но часто (особенно в бизнес приложениях) весь интерфейс можно собрать "из одного кружка". Вот пример довольно простых вариантов.

Часто весь интерфейс — это набор иконок, 9-slice спрайтов и градиентов. Сделав один фрейм рамки для Sliced режима отображения. Используя в качестве градиентов шейдеры из этой статьи + маски. Можно собрать большую часть окон, кнопок и т.п. И это скорее подход к продакшену на старте проекта. К требованиям к художникам и так далее. Очень печально видеть в атласах какие-то огромные фоны окон, особенно если они легко делались аналогичной техникой. Допустим если брать окна посложнее, то вот пример симпатичнее сделанный так же.

Фон кнопок общий. Попап собирается из маленьких квадратов внизу и мелких спрайтов, которые делают эффект "рваной бумажки". Большие фоны просто нужны для получения размеров макета на данном листе. Получается сложное окно состоящее из атласа 256 х 128 хотя сам размер окна 388х473 и при сборке "в тупую" — это было бы два спрайта подобного размера.

То есть в основном в атласах должны быть иконки и подобные формы для 9-slice. Подробнее про 9-slice можно прочесть тут.

Важно: Почему не использовать шейдер для скруглений и подобного? Как показано выше — формы бывают самые разные, но дело не только в этом. При использовании генерации меша или шейдера трудно будет сделать в общем случае антиалиасинг, чтобы избежать лесенки на этих скруглениях. Поэтому лучше использовать спрайты и 9-slice технику.

Оптимизация моделей

С моделями важно понимать из чего складывается вес модели. Анимации мы вынесем в отдельный пункт и посмотрим что за вертексные параметры и что с ними можно делать?

Изменения веса модели в целом в Unity увидеть нельзя (только в логах редактора в сборке). Но его можно оценить, если посмотреть на меш модели. Вот для примера мы видим что вертекс в нашей модели весят 1 мб. Можем ли мы как-то это уменьшить? Да, но тут есть нюанс. Важно понимать за что отвечают вертексные параметры. Например в наших AR проектах мы пользуемся шейдерами, которым чаще всего не нужны нормали. Давайте их отключим. Это делается тут.

И вес вертексов уменьшился в два раза. При этом мы ничего не потеряли (в контексте проекта).

Так, к сожалению, поступить можно не всегда. Но в любом случае не стоит забывать, что модель состоит из вертексов и треугольников. Треугольники особо не пооптимизируешь, а вот вертексы можно. И часто данные о нормалях меша на низко производительных устройствах не нужны, так как свет запекается в текстуры.

Тут же хочется сказать про Mesh Compression не вынося это в отдельный пункт. Эта настройка тоже может позволить снизить вес модели достаточно существенно. Но она вызывает артефакты и с ней надо просто пройтись по моделям, посмотреть что ничего критичного не сломалось и оставить на нужном уровне.

Оптимизация анимаций — Подход к анимациям

Тут мы главным образом поговорим про 3д. Самым главным требованием в анимациям в 3д модели в Unity является то, что все анимации должны быть внутри одной модели. В этом плане не очень удобно то же mixamo, так как оно качает отдельный fbx на каждую анимацию. Почему это плохо? В таком случае вы просто тянете кучу лишних моделей, так как движок не понимает, что это одна и та же модель. FBX же разные.

Поэтому анимации должны быть в одном fbx и уже в Unity нарезаться на отдельные клипы.

Правда всё описанное выше важно только если вы грузите анимацию по путям. То есть они лежат в папке Resources. В остальных случаях (как меня поправили в комментариях). В логе будет fbx, но на самом деле в сборку из него пойдёт только анимация.

Остальное это лишь настройка ошибки и режима компрессии анимации, которое так же делается для каждой модели по принципу: "пока не появились критичные артефакты".

Оптимизация звука, шейдеров, кода

Тут в Unity нет ничего особо интересного в плане настроек или не такое сильное влияние на вес билда. Звук можно ещё попробовать оптимизировать снижая его качество в настройках компрессии. А по остальному "использовать всё легковесное".

Оптимизация кода движка

А вот это довольно сложно и рискованно. Делается это через отключение Built-in пакетов и включение Strip Enigne Code — High. На том же андроид это позволяет выиграть около 5мб общего веса приложения. И лучше эту настройку включать на старте проекта чтобы понимать что именно сломалось. Так как Unity часто скажет не "в чём проблема", а скажет "попробуй отключить Strip Engine Code". Это может сломать часть функционала, сломать ассет бандлы, сломать много чего ещё. Но пользоваться этим можно.

В первую очередь для этого важно разбираться в том, что такое link.xml, что подробно описано в мануалах Unity по стрипингу и по Unity linker'у. Но сама тема того, как с этим работать чтобы при создании бандлов ничего не ломалось — тянет на отдельную статью.

В заключении — чеклист

Спасибо за внимание! В конце хочется собрать небольшой список действий, который стоит проходить перед релизом проекта или новой фичи чтобы сохранять размер сборки небольшим. Но сначала хочется сказать про то о чём не было сказано. Про основной инструмент анализа размера билда. Лог редактора.

Если вы изначально не нацелены на задачу "вес билда должен быть минимальным" как это делается скажем для промо-проектов в вебе или playable ads. Чаще всего достаточно пожать текстуры и 3д модели. Остальные оптимизации начинаются когда "очень надо выиграть последний мегабайт". Но в первую очередь надо посмотреть что в целом занимает место в сборке. По логу чаще всего будет сразу видно странности и где "что-то не так".

Итак, а теперь чек-лист:

  1. Посмотреть лог редактора по сборке и найти странности

  2. Проверить что все текстуры лежат в атласах

  3. Настроить сжатие атласов под целевые платформы

  4. Проверить в сборке нет градиентов, которые можно заменить шейдером

  5. Посмотреть вес самых больших 3д моделей и попробовать поменять Mesh Comprassion проверяя результат на устройствах

  6. Если какие-то вертексные параметры не используются попросить моделлеров удалить их из модели и отключить их импорт в Unity

  7. Проверить что в проекте нет "дубликатов моделей" ради анимаций

  8. Опционально: Пройтись по настройкам качества звуков и для самых больших поискать баланс между качеством и размером

  9. К крайнем случае: Включить Strip Engine Code — High и починить всё, что сломается (никогда не делать прям перед релизом)

В общем всё. Остальное уже тонкие оптимизации зависящие от контекста проекта. Типа техники палитр или же паковки множества текстур в одну текстуру. Как можно увидеть в статье многие оптимизации делаются не в последний момент, а выстраивается на уровне процессов. Так что желаю всем небольших сборок и больших успехов в разработке игр! Подписывайтесь на мой блог в телеграм, там много интересного.

Теги:
Хабы:
Всего голосов 19: ↑19 и ↓0+19
Комментарии14

Публикации

Истории

Работа

Ближайшие события