Оптимизация текстурных атласов мобильной игры
Неправильно упакованные текстуры — одна из самых частых причин того, что игра занимает 300 МБ вместо 80 МБ, а на старых Android-устройствах вылетает с SIGKILL из-за OOM. При этом в редакторе всё работает нормально: Unity хранит текстуры в несжатом виде, и реальный размер VRAM становится очевиден только при профилировании на девайсе.
Типичные проблемы с атласами
Формат по умолчанию — RGBA32. Если не задать явный Override для каждой платформы, Unity упакует текстуры в несжатый RGBA32. 1024×1024 в RGBA32 — 4 МБ VRAM. Те же данные в ASTC 6×6 — около 250 КБ. При десятке таких текстур разница становится существенной.
Размер атласа не кратен степени двойки. GPU не умеет эффективно работать с текстурами размером 700×900. Unity предупреждает об этом, но автоматически не исправляет. Non-power-of-two текстуры не сжимаются большинством форматов и занимают больше памяти, чем ближайший NPOT.
Один атлас для всего. Все спрайты в одном атласе 4096×4096 — это 16 МБ только для одной текстуры в RGBA32. При переходе на другой экран весь атлас остаётся в памяти, даже если используется 10% спрайтов.
Прозрачность там, где она не нужна. JPEG нельзя использовать для спрайтов с прозрачностью, но PNG с полностью непрозрачным фоном упаковывается как RGBA вместо RGB — лишний канал без смысла.
Форматы сжатия: что выбрать
| Платформа | Формат | Качество | Применение |
|---|---|---|---|
| Android (большинство устройств) | ASTC 6×6 | высокое | все текстуры |
| Android (legacy, API < 23) | ETC2 | среднее | непрозрачные; ETC2 RGB для alpha |
| iOS | ASTC 6×6 | высокое | все текстуры |
| iOS (fallback) | PVRTC | низкое | только при крайней нехватке памяти |
ASTC — адаптивный, поддерживает любое соотношение сторон, доступен на всех устройствах с Android 5.0+ и iOS A8+. Для игровых спрайтов 6×6 даёт хорошее соотношение качество/размер. Для UI с мелким текстом — 4×4.
ETC2 на Android нужен только если целевая аудитория — устройства старше 2015 года. В 2024 году это редкость, но если у проекта есть данные аналитики с долей таких устройств > 5% — учитываем.
Структура атласов по слоям
Правильная стратегия — разбивка атласов по контексту использования, а не по типу объекта:
- ui-hud: элементы HUD, отображаемые постоянно во время игры
- ui-menus: кнопки, фоны, иконки для меню (выгружаются во время геймплея)
- gameplay-player: спрайты игрока и его анимации
- gameplay-enemies-tier1: враги первого уровня
- gameplay-vfx: частицы, взрывы, эффекты
Такая разбивка позволяет выгружать неиспользуемые атласы через Resources.UnloadUnusedAssets() или через Addressables с явным Release. При едином атласе на всю игру это невозможно.
Пустое пространство в атласе
Unity SpriteAtlas оставляет padding между спрайтами (по умолчанию 4 px) для предотвращения bleeding. На атласе 1024×1024 это может давать до 15–20% потерь площади. Паддинг можно уменьшить до 2 px для спрайтов без субпиксельного рендеринга, и это заметно улучшает упаковку.
Смотреть реальный процент заполнения можно в Preview атласа в инспекторе. Если меньше 70% — стоит переработать разбивку.
Процесс оптимизации
Начинаем с Memory Profiler (Window → Analysis → Memory Profiler) на реальном девайсе: смотрим раздел Textures, сортируем по размеру. Берём топ-10 самых тяжёлых текстур — в 80% случаев там несжатые атласы или PNG без platform-specific настроек.
Дальше: настройка Overrides для Android/iOS в каждом атласе, реструктуризация по контексту использования, настройка Mip Maps (для 2D-игр обычно отключаем — экономия 33% памяти на каждой текстуре), проверка POT-размеров.
Финальная проверка — Android GPU Inspector или Xcode Metal System Trace. Смотрим размер VRAM до и после.
Сроки: три-шесть рабочих дней в зависимости от количества атласов и наличия Addressables в проекте.







