Оптимизация отрисовки (Draw Calls) в играх
200 Draw Calls на мобильном устройстве при отрисовке UI через Canvas в Overlay-режиме — это не редкость. Это типичная ситуация на проекте, который «просто сделали», не думая о batching-стратегии с самого начала. К тому моменту, когда начинается оптимизация, в сцене уже 15 уникальных материалов на UI-элементах, каждый Sprite рендерится отдельным вызовом, а GPU на iPhone 12 выдаёт 28 fps там, где должно быть 60.
Draw Call — это команда CPU к GPU: «нарисуй вот этот mesh с вот этим материалом». Каждый вызов несёт overhead на стороне CPU (State Change, Command Buffer preparation). На мобильных чипах этот overhead критичен. На PC — меньше, но тоже считается.
Где Draw Calls растут бесконтрольно
Самый частый источник — Unity Canvas. Стандартная ошибка: несколько Canvas-элементов с разными материалами в одном Canvas Root. Каждая смена материала — новый Draw Call. Решение: все UI-спрайты в один Sprite Atlas, один материал на весь Canvas. Canvas Rebuild при изменении одного элемента перерисовывает весь Canvas — разбиваем динамические элементы в дочерний Canvas.
Скиннинг и анимированные персонажи. SkinnedMeshRenderer не участвует в стандартном Static Batching и плохо поддаётся GPU Instancing в Unity (нужен кастомный подход через Graphics.DrawMeshInstanced с предвычисленными bone matrices). Если в сцене 50 одинаковых NPC — это 50 отдельных Draw Calls по умолчанию.
Particle System с уникальными материалами. Каждая Particle System с уникальным материалом — отдельный Draw Call, даже если система стоит из 2 частиц. На мобильном проекте видели 60 Draw Calls только от партиклов в одной локации.
Dynamic GI и real-time освещение. Каждый дополнительный real-time источник света в Forward Rendering увеличивает Draw Calls пропорционально количеству объектов, попавших в радиус. 3 point-light'а в комнате × 20 объектов = 60 дополнительных вызовов. Deferred Rendering решает это архитектурно, но требует поддержки G-Buffer.
Инструменты и конкретные техники снижения
SRP Batcher — первое, что включаем в URP/HDRP проектах. Не уменьшает количество Draw Calls, но резко снижает CPU overhead через унификацию Constant Buffer layout. Требует, чтобы все шейдеры были SRP Batcher-compatible (проверяем в Shader Inspector — должна быть надпись «compatible»). Если шейдер написан под Built-in Pipeline и не переписан — SRP Batcher на него не распространяется.
GPU Instancing — для повторяющихся мешей с одним материалом. Включается галочкой в Material Inspector. В нативном виде работает только для одинаковых мешей с одинаковыми материалами. Для разных цветов/параметров — MaterialPropertyBlock. Типичный кейс: 200 деревьев одного типа → 1 Draw Call вместо 200.
Static Batching — помечаем статичные объекты как Static, Unity при сборке объединяет их меши в один большой VBO. Минус: увеличивается потребление памяти, так как каждый batched mesh хранится отдельно. На мобильных проектах с ограниченным RAM — баланс между Draw Calls и памятью.
Dynamic Batching — для мелких мешей (меньше 900 вершин). В URP включён по умолчанию, но на практике почти не работает для большинства игровых объектов — слишком строгие требования к verts count и UV-каналам. Лучше не рассчитывать на него как на основной инструмент.
Frame Debugger — основной инструмент диагностики. Открываем, начинаем Play, нажимаем Enable. Видим каждый Draw Call с объяснением, почему он не был batched («different materials», «not in same layer», «different lightmap indices»). Именно здесь понимаем реальную картину, а не ту, что показывает Stats в Game View.
Реальный кейс: мобильная Tower Defense, сцена с 380 Draw Calls. Frame Debugger показал: 80 башен одного типа — не инстансятся, потому что у каждой уникальный LightProbe baked (из-за того, что они были перемещены после запечки освещения и не переиндексированы). Пересборка Light Probe Groups + включение GPU Instancing → 80 вызовов превратились в 4. Общий результат по сцене: 380 → 140 Draw Calls, fps на Samsung Galaxy S21 вырос с 38 до 58.
Как выстраиваем работу
Первый шаг — снимаем метрики через Unity Profiler в режиме Standalone (не Editor). Editor добавляет свои вызовы и искажает картину. Подключаем устройство через USB, Deep Profile только если нужна точная атрибуция по скриптам.
Анализируем через Frame Debugger категории Draw Calls: UI, Environment, Characters, VFX, Shadow Casters. Для каждой категории — своя стратегия batching.
Готовим план изменений с оценкой impact. Изменение стратегии batching для UI занимает 1–2 дня. Переработка архитектуры материалов для персонажей — неделя. Внедрение GPU Instancing для растительности — 2–3 дня.
| Масштаб задачи | Ориентировочные сроки |
|---|---|
| Аудит + отчёт с рекомендациями | 2–3 дня |
| Оптимизация UI-слоя (Canvas batching) | 3–5 дней |
| Оптимизация игровой сцены (окружение + пропсы) | 1–3 недели |
| Полная переработка Draw Call-стратегии проекта | 4–8 недель |
Стоимость рассчитывается индивидуально после аудита проекта.





