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

Какие критерии необходимы для dynamic batching?

2.0 Middle🔥 192 комментариев
#Оптимизация#Рендеринг и графика

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

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

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

Критерии и условия для Dynamic Batching в Unity

Dynamic Batching — это техника оптимизации рендеринга, которая автоматически объединяет несколько мелких мешей в один большой пакет (batch) во время выполнения, чтобы уменьшить количество вызовов отрисовки (draw calls). Для успешного батчинга должны соблюдаться строгие критерии, которые я разделю на основные, материальные и ограничения.

Основные критерии для динамического батчинга

  1. Тип и сложность меша:

    • Меш должен содержать не более 300 вершин (после трансформации в мировое пространство).
    • Используется только для мешей, созданных из треугольников (не подходит для линий, точек).
    • Меши должны использовать один и тот же материал. Разные материалы предотвращают батчинг.
  2. Трансформации и масштабирование:

    • Объекты должны иметь равномерное масштабирование (одинаковый масштаб по всем осям). Неравномерное масштабирование часто ломает батчинг.
    • Не поддерживаются объекты с зеркальным отражением (отрицательный масштаб).
  3. Источник меша:

    • Батчатся только меши, созданные встроенными примитивами Unity (Cube, Sphere, Plane и т.д.) или импортированные 3D-модели.
    • Не батчатся меши, созданные через Mesh.Create() или ProceduralMesh во время выполнения (если не соблюдены особые условия).

Критерии, связанные с материалами и шейдерами

  1. Идентичность материалов:

    // Эти объекты СМОГУТ объединиться в батч
    GameObject cube1 = GameObject.CreatePrimitive(PrimitiveType.Cube);
    GameObject cube2 = GameObject.CreatePrimitive(PrimitiveType.Cube);
    Material sharedMat = Resources.Load<Material>("MyMaterial");
    cube1.GetComponent<Renderer>().sharedMaterial = sharedMat;
    cube2.GetComponent<Renderer>().sharedMaterial = sharedMat;
    
    // Эти объекты НЕ объединятся (разные материалы)
    cube1.GetComponent<Renderer>().material.color = Color.red;  // Создает инстанс материала!
    cube2.GetComponent<Renderer>().material.color = Color.blue; // Другой инстанс
    
    • Критически важно использовать sharedMaterial, а не material (который создает уникальную копию).
    • Шейдер должен поддерживать батчинг (большинство встроенных шейдеров Unity поддерживают).
  2. Параметры шейдера:

    • Если шейдер использует разные текстуры, цвета или float-параметры — батчинг нарушается.
    • Шейдеры с сложной вершинной анимацией или морфингом обычно не батчатся.

Ограничения и исключения

  • Тени и лайтмапы: Объекты, принимающие реальные тени (Shadow Casters), имеют дополнительные ограничения для батчинга.
  • GPU Skinning: Меши с анимацией костей (SkinnedMeshRenderer) не могут быть динамически забатчены (для них используется другой метод — GPU Skinning).
  • Прозрачные материалы: Для прозрачных (alpha-blended) материалов условия строже, так как порядок отрисовки важен.
  • Проверка в редакторе: В окне Stats или через Frame Debugger можно видеть, сколько батчей создано и почему объекты не объединились.

Практические рекомендации

  • Всегда проверяйте Frame Debugger (Window → Analysis → Frame Debugger) для диагностики.
  • Для статических объектов используйте Static Batching (отметка Static в инспекторе) — он более эффективен и имеет меньше ограничений.
  • Для одинаковых объектов, которые нельзя забатчить динамически, рассмотрите GPU Instancing.
  • Следите за лимитом в 300 вершин — это включает все вершины после применения трансформаций.

Пример проверки возможности батчинга

void CheckBatchingCriteria(GameObject obj)
{
    MeshFilter mf = obj.GetComponent<MeshFilter>();
    if (mf != null && mf.sharedMesh != null)
    {
        Debug.Log($"Вершин в меше: {mf.sharedMesh.vertexCount}");
        
        // Проверка масштаба
        if (obj.transform.lossyScale.x != obj.transform.lossyScale.y || 
            obj.transform.lossyScale.x != obj.transform.lossyScale.z)
        {
            Debug.LogWarning("Неравномерный масштаб предотвратит батчинг!");
        }
    }
    
    // Проверка материала
    Renderer renderer = obj.GetComponent<Renderer>();
    if (renderer != null)
    {
        if (renderer.sharedMaterial == null)
            Debug.LogError("Нет материала!");
        else if (renderer.sharedMaterial != renderer.material)
            Debug.LogWarning("Используется material вместо sharedMaterial!");
    }
}

В современных проектах Dynamic Batching часто заменяется более эффективными методами вроде SRP Batcher или GPU Instancing, но понимание его критериев остается важным для оптимизации рендеринга, особенно на мобильных платформах и в специфических сценариях.