Производительность мобильной игры почти никогда не упирается в одну-единственную причину. Обычно это комбинация: рендеринг, память, код, физика, UI и загрузка ресурсов работают вместе, и узкое место может быть неочевидным. Если оптимизировать всё подряд без замеров, легко потратить недели и не получить заметного прироста FPS. В студии мы через это проходили не раз, и главный урок — начинать нужно с профилировщика, а не с интуиции.
Ниже — практический разбор того, что реально влияет на производительность мобильной игры в Unity, как это диагностировать и что исправлять в первую очередь. Все рекомендации основаны на реальных кейсах из разработки казуальных проектов и обучении стажёров.
Почему мобильная оптимизация отличается от ПК
На телефоне у игры обычно меньше запас по CPU, GPU и памяти, чем на десктопе. Поэтому то, что «летает» в редакторе или на мощном устройстве, может тормозить на среднем Android-смартфоне. Мы не раз наблюдали, как сцена, собранная на скорую руку, показывала 60 FPS на флагмане и 15 FPS на бюджетнике трёхлетней давности.
Ключевая ошибка новичков — ориентироваться только на FPS в Editor. Для мобильных игр важнее тестировать на целевых устройствах и сравнивать поведение на слабых и сильных моделях. В Unity прямо рекомендуют профилировать development build на реальном устройстве и проверять проект на самых слабых и самых сильных девайсах из целевой линейки. Когда я веду стажёров, первое, что заставляю сделать — запустить билд на старом телефоне и посмотреть, где именно начинаются просадки.
С чего начинать оптимизацию
Самый правильный порядок такой:
1. Найти узкое место.
2. Исправить его.
3. Снова замерить.
4. Сравнить результат до и после.
Это звучит банально, но именно так экономится время. Unity советует сохранять данные профилировщика до изменений, вносить правку и сравнивать метрики после неё. В наших проектах мы всегда делаем снапшоты профайлера перед любой серьёзной оптимизацией — это даёт объективную картину, а не ощущения «вроде стало лучше».
Что именно измерять
— Время кадра CPU.
— Время кадра GPU.
— Количество draw calls.
— Использование памяти.
— Частоту и длительность GC.
— Время загрузки сцены.
— Пики при подгрузке контента.
Если неясно, где проблема, оптимизация превращается в угадайку. А угадайка в мобильной разработке обычно заканчивается потерянной неделей. Один из наших стажёров как-то потратил три дня на переписывание шейдеров, хотя тормоза были из-за сотен динамических текстов в UI. Профилировщик показал бы это за пять минут.
Основные источники тормозов в мобильной игре
1. Слишком дорогой рендеринг
Это один из самых частых сценариев. На телефоне важно не только «что рисуется», но и **как часто** меняется состояние рендера. Каждое переключение материала или текстуры — это накладные расходы, которые на слабом GPU быстро складываются в заметные просадки.
К рендеринговым проблемам обычно относятся:
— большое число материалов;
— много отдельных текстур вместо атласа;
— лишние прозрачные слои;
— тяжёлые шейдеры;
— избыток draw calls.
Unity в мобильной документации отдельно рекомендует держать число материалов как можно ниже, использовать texture atlases и избегать тяжёлых альфа-эффектов, особенно Cutout и больших областей прозрачности. В казуальных играх, где на экране много мелких иконок и спрайтов, это правило работает безотказно.
Что делать
— Объединяйте мелкие спрайты в атласы.
— Используйте меньше материалов.
— По возможности опирайтесь на sharedMaterial, а не на material, если работаете с общими настройками и атласами.
— Уменьшайте площадь прозрачных поверхностей на экране.
— Избегайте сложных шейдерных эффектов без необходимости.
В одном из наших проектов мы сократили число материалов с 47 до 12 только за счёт перехода на атласы и переиспользования материалов — draw calls упали почти вдвое, а FPS на слабых устройствах поднялся с 22 до 40.
2. Тяжёлые шейдеры
На мобильных устройствах шейдер должен быть максимально простым. Unity рекомендует использовать простые mobile shaders, уменьшать количество вычислений и избегать дорогих математических операций вроде pow, exp, log, sin, cos и tan. Даже одна такая операция на пиксель может стать бутылочным горлышком, если она выполняется для всего экрана.
Типичные ошибки
— многофункциональный универсальный шейдер «на все случаи жизни»;
— эффекты, которые красиво выглядят, но не дают игрового смысла;
— чрезмерное число вариантов шейдера;
— работа с высокой точностью там, где хватило бы более лёгкой.
Практика
Если эффект заметен только в статичном скриншоте, а в игре его почти не видит игрок, скорее всего, он не стоит своих затрат. Мы в студии часто отказывались от красивых бликов и мягких теней в пользу стабильных 60 FPS — игроки этого даже не замечали, а вот лаги замечали сразу.
3. Плохая организация батчинга
Батчинг помогает Unity объединять объекты и уменьшать количество draw calls. Это снижает нагрузку на CPU при отрисовке. В мобильных проектах это один из самых дешёвых способов получить прирост производительности без изменения логики.
Unity и связанные материалы по оптимизации выделяют несколько важных приёмов:
— Static batching для неподвижной геометрии;
— SRP Batcher в URP;
— уменьшение количества материалов;
— одинаковые настройки материалов у объектов, которые должны рисоваться вместе.
Когда батчинг ломается
— разные материалы у похожих объектов;
— лишние уникальные текстуры;
— динамическое изменение материала для каждого экземпляра;
— прозрачные объекты, которые приходится сортировать.
На одном из проектов мы обнаружили, что батчинг перестал работать после того, как художник назначил каждому элементу UI свой экземпляр материала. Возврат к общему материалу и атласу мгновенно сократил draw calls на 30%.
4. Избыточная нагрузка на CPU
Если игра тормозит даже при простом рендере, проблема часто в логике: Update на тысячах объектов, частые аллокации, лишняя физика, сложные проверки каждый кадр. В мобильных играх CPU часто перегружен не графикой, а тем, что разработчик не заметил, сколько объектов висит в Update.
Unity рекомендует профилировать именно на реальном устройстве, чтобы понять, что съедает время кадра: рендер, логика, физика или память. В наших казуальных проектах мы не раз находили, что 80% времени кадра уходит на поиск объектов по имени или на обработку событий, которые можно было бы вызывать раз в секунду.
Что проверять в первую очередь
— сколько объектов живёт в Update;
— не создаются ли временные объекты каждый кадр;
— нет ли тяжёлых вычислений в циклах;
— не вызывается ли дорогая логика слишком часто;
— не перегружена ли физика.
5. Неоптимальная работа с памятью
На мобильных устройствах память заканчивается быстро. Когда игра начинает активно выделять и освобождать память, появляются фризы, а иногда и вылеты. GC может вызывать заметные подёргивания, особенно на устройствах с 2–3 ГБ ОЗУ.
Unity советует следить за памятью отдельно и сравнивать состояние до и после оптимизаций. Для мобильных игр это особенно важно, потому что текстуры и ассеты часто занимают больше, чем ожидается. Мы в студии всегда держим под рукой профайлер памяти и проверяем, не растёт ли потребление после нескольких циклов загрузки/выгрузки сцен.
Что обычно раздувает память
— слишком большие текстуры;
— дублирующиеся ассеты;
— неиспользуемые ресурсы в сцене;
— лишние экземпляры материалов;
— частые временные выделения в коде.
6. Большие и тяжёлые текстуры
Текстуры — один из главных потребителей памяти и пропускной способности. Unity в документации по мобильной оптимизации советует сжимать текстуры, использовать mipmaps там, где это уместно, и снижать разрешение до разумного минимума. В казуальных играх текстуры часто занимают 60–70% всей памяти, и их оптимизация даёт самый быстрый эффект.
Практический подход
— для UI и иконок — отдельные атласы;
— для фонов — уменьшение разрешения, если игрок не видит мелких деталей;
— для мелких объектов — не держать текстуры «с запасом»;
— для мобильных платформ — использовать подходящий формат сжатия.
Однажды мы уменьшили разрешение фоновых текстур на 30%, и никто из тестировщиков не заметил разницы, а потребление памяти упало на 80 МБ. Это позволило игре стабильно работать на устройствах с 2 ГБ ОЗУ.
Таблица: что сильнее всего влияет на FPS
| Проблема | Как проявляется | Что делать |
|---|---|---|
| Много draw calls | просадки на CPU, особенно в сценах с множеством объектов | батчинг, атласы, меньше материалов |
| Тяжёлые шейдеры | падение FPS на GPU | упрощать шейдеры, убрать дорогие операции |
| Большие текстуры | лаги, память быстро растёт | сжимать, уменьшать размер, объединять в атласы |
| Частые аллокации | фризы и подёргивания | убрать мусор из Update, переиспользовать объекты |
| Избыточная физика | нестабильный frame time | снизить число коллайдеров и частоту расчётов |
| Сложный UI | лишняя нагрузка даже в меню | уменьшить анимации, слои и обновления |
Практический порядок оптимизации в Unity
Шаг 1. Зафиксируйте базовую метрику
Перед изменениями снимите профиль на устройстве. Иначе нельзя будет доказать, что улучшение действительно сработало. Мы всегда сохраняем скриншоты профайлера и записываем ключевые цифры в таблицу, чтобы потом не спорить с коллегами о том, стало ли лучше.
Шаг 2. Найдите главный bottleneck
Если CPU загружен, нет смысла первым делом переписывать шейдеры. Если GPU упирается в рендер, бессмысленно начинать с микроправок в логике. Профайлер чётко покажет, кто именно съедает кадр. В одном проекте мы думали, что проблема в физике, а оказалось — в тысяче мелких прозрачных спрайтов, которые убивали GPU.
Шаг 3. Уберите самые дорогие ошибки
Обычно это:
— слишком много материалов;
— лишняя прозрачность;
— огромные текстуры;
— аллокации в горячих местах;
— тяжёлая логика в Update.
Устранение одной такой ошибки может поднять FPS на 10–20 кадров, тогда как правка десяти мелких даст в сумме 2–3.
Шаг 4. Проверьте результат на слабом устройстве
Оптимизация ради флагмана не решает проблему массовой аудитории. В России у пользователей очень разный парк смартфонов, и ориентироваться нужно не на один «эталонный» телефон, а на несколько классов устройств. Мы тестируем на трёх-четырёх моделях: бюджетный Xiaomi трёхлетней давности, средний Samsung, флагман и что-то совсем старое с 2 ГБ ОЗУ.
Шаг 5. Повторите цикл
Профиль → правка → замер → сравнение. Именно этот цикл даёт стабильный результат. В студии мы проходим его минимум три-четыре раза перед релизом, и каждый раз находится что-то новое.
Как понять, что проблема именно в рендеринге
Есть несколько признаков:
— FPS падает, когда на экране много объектов;
— исчезновение части объектов резко улучшает производительность;
— просадки сильнее в бою, чем в меню;
— уменьшение сложности шейдера даёт заметный эффект.
Unity отдельно подчёркивает пользу batching, атласов и упрощения шейдеров как способа уменьшить CPU-накладные расходы на рендеринг. В казуальных играх рендеринг часто становится узким местом из-за обилия UI и спрайтов, поэтому мы всегда начинаем диагностику именно с него.
Быстрый чек-лист по рендеру
— [ ] В проекте минимальное число материалов.
— [ ] Мелкие спрайты собраны в атласы.
— [ ] Лишняя прозрачность убрана.
— [ ] Используются простые шейдеры.
— [ ] Проверен SRP Batcher, если проект на URP.
— [ ] Отдельно проверены статические объекты.
Как понять, что проблема в коде
Если графика простая, а игра всё равно фризит, ищите ошибку в логике. В наших проектах такое случалось, когда кто-то вставлял FindObjectOfType в Update или генерировал строки для отладки каждый кадр.
Частые причины
— создание объектов каждый кадр;
— постоянные поиски по сцене;
— тяжёлые расчёты в Update;
— частые обращения к строкам, спискам и LINQ в горячем коде;
— избыточные события и подписки.
Что помогает
— выносить расчёты из Update;
— использовать кэширование;
— переиспользовать объекты;
— сокращать частоту вызовов;
— проверять, что действительно должно выполняться каждый кадр.
Один из самых памятных случаев: игра фризила каждые две секунды, потому что в корутине каждую секунду вызывался Resources.Load для одного и того же ассета. Кэширование ссылки убрало фризы полностью.
Особенности UI в мобильной игре
UI часто недооценивают. При этом именно меню, окна, HUD и анимации могут заметно грузить слабые устройства. В казуальных проектах UI может занимать до 40% времени кадра, если сделан без оглядки на производительность.
На что смотреть
— количество активных элементов;
— анимации и эффекты;
— частоту обновления текста и прогресса;
— число отдельных атласов;
— постоянные перестроения layout.
Если интерфейс меняется редко, не стоит заставлять его пересчитываться без необходимости. Мы часто отключаем обновление текста, когда оно не видно игроку, и группируем статичные элементы на отдельных канвасах, чтобы не перестраивать весь UI при изменении одного счётчика.
Ошибки, которые чаще всего делают начинающие
— Оптимизируют без профилировки.
— Смотрят только на FPS в редакторе.
— Добавляют атлас, но оставляют десятки разных материалов.
— Пишут тяжёлые шейдеры для декоративных эффектов.
— Не замечают, что память утекает из-за текстур.
— Проверяют только один смартфон и считают результат универсальным.
— Улучшают второстепенные места, пока главный bottleneck остаётся нетронутым.
Из опыта обучения стажёров добавлю ещё одну: пытаются оптимизировать всё сразу, не фиксируя промежуточные результаты. В итоге невозможно понять, какое изменение сработало, а какое — нет.
Когда оптимизацию надо начинать
Лучше не ждать финального этапа. Базовые решения по производительности стоит закладывать ещё на стадии прототипа:
— не плодить материалы без необходимости;
— сразу думать о размере текстур;
— не строить архитектуру, где всё обновляется каждый кадр;
— тестировать на устройстве с самого начала;
— держать рендер и код в контролируемом состоянии.
Поздняя оптимизация почти всегда дороже. Если проект уже собран из десятков тяжёлых решений, исправлять его приходится точечно и долго. Мы в студии стараемся уже на этапе серого прототипа закладывать структуру, которая не развалится при масштабировании, и проверяем производительность на целевых устройствах раз в две недели.
Итог
Оптимизация мобильной игры в Unity — это не набор магических лайфхаков, а системная работа с узкими местами. Чаще всего производительность проседает из-за рендера, тяжёлых шейдеров, большого числа материалов, плохой работы с памятью и лишней логики в коде.
Самый надёжный путь — профилировать на реальных устройствах, сравнивать результаты до и после правок и в первую очередь убирать самые дорогие ошибки. Для мобильных игр особенно важны атласы, батчинг, простые шейдеры, умеренные текстуры и аккуратная логика без лишних аллокаций.
FAQ
С чего начать оптимизацию мобильной игры в Unity?
С профилирования на реальном устройстве. Без замеров нельзя понять, что именно тормозит: рендер, CPU, память или физика. Подключите телефон, запустите development build и снимите данные профайлером — это даст точную картину.
Что сильнее всего влияет на FPS?
Обычно это количество draw calls, сложные шейдеры, тяжёлые текстуры, лишняя прозрачность и дорогая логика в коде. В казуальных играх первые два пункта часто оказываются главными виновниками.
Нужно ли всегда использовать texture atlases?
Для мобильных игр — почти всегда это хорошая идея, особенно для спрайтов, иконок и UI. Unity рекомендует атласы как способ сократить число переключений состояния и облегчить batching. Исключение — очень крупные уникальные текстуры, которые не с чем объединять.
Почему игра тормозит только на телефоне, но не в редакторе?
Потому что Editor не отражает реальную нагрузку устройства. На мобильном ограничены CPU, GPU и память, поэтому тестировать нужно на целевых девайсах. Даже мощный ПК с редактором не покажет, как игра поведёт себя на бюджетном смартфоне с медленной памятью.
Что важнее: оптимизация кода или графики?
Зависит от bottleneck. Если упираетесь в рендер — оптимизируйте графику. Если тормозит логика — сокращайте работу кода. Начинать нужно не с догадок, а с профилировщика. Он покажет, кто именно съедает кадр.
Можно ли делать красивую мобильную игру без просадок?
Да, если заранее ограничивать число материалов, следить за размером текстур, упрощать шейдеры и не перегружать сцену лишними эффектами. Красота и производительность не исключают друг друга, если думать об оптимизации с самого начала.
