← Назад к вопросам

Что такое Draw Call и Batching в Unity? Как их оптимизировать?

1.6 Junior🔥 201 комментариев
#Unity Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Draw Call и Batching: Основные понятия

В контексте рендеринга в Unity, Draw Call (Вызов отрисовки) — это команда, отправляемая графическому API (DirectX, OpenGL, Vulkan) для отрисовки одного меша (сетки) с определенным материалом и текстурой на графический процессор (GPU). Каждый вызов имеет накладные расходы, и их чрезмерное количество — главный источник проблем с производительностью рендеринга.

Batching (Пакетирование) — это процесс объединения нескольких объектов в один или несколько Draw Call'ов для минимизации их общего числа. Это ключевая техника оптимизации.

Типы Batching в Unity

1. Динамический Batching (Dynamic Batching)

Unity в реальном времени объединяет мелкие динамические объекты (перемещающиеся, анимированные) в один Draw Call.

  • Как работает: Автоматически для объектов, удовлетворяющих строгим критериям (например, < 300 вершин, один материал, единый масштаб трансформации).
  • Ограничения: Высокие накладные расходы на CPU для расчета объединения каждый кадр. Неэффективен для сложных объектов.
// Пример: Объекты с этим материалом могут быть динамически сбатчены,
// если они маленькие и используют тот же материал.
public Material sharedMaterial;

2. Статический Batching (Static Batching)

Объединение объектов, которые не двигаются в течение игры, в большие статические меши.

  • Как работает: Отмечаем объект как Static в инспекторе (или через код). Unity предварительно (при сборке или во время выполнения) объединяет их геометрию в общие Vertex/Index Buffer'ы.
  • Преимущества: Огромный выигрыш в производительности рендеринга для статичной геометрии (окружение, ландшафт).
  • Недостаток: Увеличивает потребление памяти (VRAM), так как хранит объединен ную геометрию.
// Можно пометить статическим через код (но обычно делается в инспекторе).
gameObject.isStatic = true;

3. GPU Instancing

Продвинутая техника, позволяющая отрисовывать множество одинаковых мешей с одним материалом, но разными параметрами (позиция, цвет), используя один Draw Call.

  • Как работает: На GPU отправляется один меш и массив данных (матрицы трансформации, цвета). Шейдер обрабатывает их все за один проход.
  • Идеально для: Травы, деревьев, пуль, однотипных зданий.
// Пример структуры в шейдере для поддержки инстансинга (Surface Shader)
#pragma surface surf Standard fullforwardshadows addshadow
#pragma multi_compile_instancing // Ключевая директива

struct Input { float2 uv_MainTex; };
UNITY_INSTANCING_BUFFER_START(Props)
    UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
UNITY_INSTANCING_BUFFER_END(Props)

void surf (Input IN, inout SurfaceOutputStandard o) {
    float4 c = UNITY_ACCESS_INSTANCED_PROP(Props, _Color);
    o.Albedo = c.rgb;
}

Стратегии оптимизации Draw Call'ов и Batching

1. Минимизация и управление материалами

  • Атлас текстур (Texture Atlasing): Объединяйте несколько мелких текстур для разных объектов в одну большую текстуру. Это позволяет использовать один материал для многих объектов, что критично для эффективного батчинга.
  • Общие материалы (Shared Materials): Используйте один экземпляр Material для множества объектов, а не копии (Material Instances). Изменение свойства материала-копии "разрывает" батч.

2. Рациональное использование статического батчинга

  • Помечайте как Static только те объекты, которые действительно неподвижны (стены, пол, крупный декор).
  • Следите за потреблением памяти. Разделяйте большую сцену на логические части (например, комнаты) с разными статическими батчами.

3. Активное применение GPU Instancing

  • Включайте опцию Enable GPU Instancing в материалах, особенно для пользовательских или стандартных шейдеров, которые ее поддерживают.
  • Используйте для рендеринга множества однотипных объектов через скрипт Graphics.DrawMeshInstanced или Graphics.DrawMeshInstancedIndirect для продвинутого контроля.
// Пример рисования мешей с инстансингом через Graphics API
public Mesh instanceMesh;
public Material instanceMaterial;
Matrix4x4[] matrices = new Matrix4x4[1000];

void RenderInstances() {
    // Заполните массив matrices трансформациями ваших объектов
    Graphics.DrawMeshInstanced(instanceMesh, 0, instanceMaterial, matrices);
}

4. Работа с UI (Canvas)

  • Элементы UI (uGUI) рендерятся отдельно. Каждый Canvas генерирует свои собственные Draw Call'ы для своих элементов.
  • Стратегия: Минимизируйте количество активных Canvas компонентов. Объединяйте статичные UI-элементы на одном Canvas, а динамические (например, health bar) выносите на отдельные, более мелкие Canvas.

5. Использование инструментов анализа

  • Окно Frame Debugger (Window > Analysis > Frame Debugger): Позволяет пошагово увидеть каждый Draw Call, понять, какие объекты были сбатчены, а какие нет, и почему.
  • Статистика в Game View (Stats): Следите за показателями SetPass calls и Batches. Цель — снижать их количество без ущерба для визуального качества.

6. Оптимизация LOD (Level of Detail) и Occlusion Culling

  • LOD Group: Показывайте низкополигональные версии объектов на расстоянии, что уменьшает сложность мешей и может упростить батчинг.
  • Occlusion Culling (Unity's Occlusion Area): Не рендерьте объекты, которые закрыты другими (например, стенами). Прямо не уменьшает количество Draw Call'ов на объект, но снижает общее количество отрисовываемых объектов в кадре.

Итог: Оптимизация рендеринга — это баланс между количеством Draw Call'ов, потреблением памяти (VRAM) и загрузкой CPU. Ключ — максимальное использование статического батчинга для окружения, активное внедрение GPU Instancing для повторяющихся объектов, скрупулезная работа с материалами и текстурами и постоянный анализ с помощью Frame Debugger.

Что такое Draw Call и Batching в Unity? Как их оптимизировать? | PrepBro