Unity 模型渲染优化:从 Batching 到 GI 设置的完整指南

引言

Unity 模型渲染优化是提升游戏性能的关键,尤其在复杂场景中,模型(Mesh)渲染占 GPU 开销的 70%以上。从 Batching(批处理)到 GI(Global Illumination,全局照明)设置,形成完整优化链条:Batching 减少 Draw Call,GI 提升光照真实感而非性能瓶颈。优化目标:Draw Call <300/帧,SetPass calls <100,GI 开销 <20ms/帧。根据 Unity 文档,批处理可降 Draw Call 50-90%,GI 需平衡质量/计算。

适用版本:Unity 2022.3 LTS+(兼容 Unity 6),URP/HDRP 优先。优化原则:减少独特渲染状态、合并网格、预计算光照。


第一部分:Batching(批处理)详解

Batching 是合并多个模型渲染的技术,减少 CPU-GPU 通信(Draw Call)。Unity 提供 4 种批处理方式:静态、动态、SRP Batcher 和 GPU Instancing。目标:单 Draw Call 渲染 100+ 模型。

1. 静态批处理(Static Batching)

原理:预合并静态模型网格为单一网格,运行时无开销。但需标记 Static。

设置

  • Edit > Project Settings > Player > Other Settings > Static Batching = Enabled
  • 物体 Inspector > Static = Batching Static

代码示例(运行时合并):

using UnityEngine;

public class StaticBatcher : MonoBehaviour
{
    public GameObject[] staticObjects;  // 拖拽静态物体

    void Start()
    {
        StaticBatchingUtility.Combine(staticObjects, gameObject);  // 合并到根
        Debug.Log("静态批处理完成");
    }
}

注意:合并后不可移动;内存增加(复制网格);适用于建筑/地形。

2. 动态批处理(Dynamic Batching)

原理:运行时合并相似动态模型(顶点<300,相同材质)。

设置

  • Project Settings > Player > Dynamic Batching = Enabled

代码示例(优化动态物体):

using UnityEngine;

public class DynamicBatcher : MonoBehaviour
{
    public Material sharedMaterial;  // 统一材质

    void Start()
    {
        Renderer[] renderers = FindObjectsOfType<Renderer>();
        foreach (var r in renderers)
        {
            if (r.gameObject.CompareTag("DynamicBatch"))
            {
                r.sharedMaterial = sharedMaterial;  // 统一材质启用批处理
            }
        }
    }
}

注意:仅简单网格;移动物体需相同 Scale;不兼容 Skinned Mesh。

3. SRP Batcher(URP/HDRP 专用)

原理:批处理材质变体,减少 SetPass calls,而非合并网格。适用于动态/静态物体。

设置

  • URP/HDRP Asset > Advanced > SRP Batcher = Enabled(默认)

代码示例(检查兼容):

using UnityEngine.Rendering;

public class SRPBatcherChecker : MonoBehaviour
{
    void Start()
    {
        var pipeline = GraphicsSettings.currentRenderPipeline;
        if (pipeline != null)
        {
            Debug.Log("SRP Batcher 启用:" + pipeline.supportsSRPBatcher);
        }
    }
}

注意:Shader 需兼容(无运行时关键词变体);移动端高效。

4. GPU Instancing

原理:单次 Draw Call 渲染多个相同网格/材质实例。

设置

  • 材质 Inspector > Enable GPU Instancing = On

代码示例

using UnityEngine;

public class GPUInstancer : MonoBehaviour
{
    public Mesh mesh;
    public Material instanceMaterial;  // 启用 Instancing 的材质

    void Start()
    {
        instanceMaterial.enableInstancing = true;
        Matrix4x4[] matrices = new Matrix4x4[100];

        for (int i = 0; i < 100; i++)
        {
            matrices[i] = Matrix4x4.TRS(Random.insideUnitSphere * 10f, Quaternion.identity, Vector3.one);
        }

        Graphics.DrawMeshInstanced(mesh, 0, instanceMaterial, matrices);
    }
}

注意:支持动态数据(矩阵数组);URP/HDRP 自动优化。

第二部分:GI(Global Illumination)设置详解

GI 模拟间接光照,提升模型真实感,但开销高。Unity 支持 Baked/Realtime/Mixed GI。

1. Baked GI(烘焙 GI)

原理:预计算光照贴图(Lightmap),运行时无开销。

设置

  • Window > Rendering > Lighting > Baked Global Illumination = On
  • Lightmapper = Progressive CPU/GPU
  • 物体 Inspector > Static = Lightmap Static

代码示例(动态烘焙):

using UnityEngine;
using UnityEngine.Experimental.GlobalIllumination;

public class GIBaker : MonoBehaviour
{
    void Start()
    {
        #if UNITY_EDITOR
        Lightmapping.Bake();  // 编辑器中烘焙
        #endif
    }

    public void UpdateGI()
    {
        Lightmapping.SetDelegate(null);  // 重置代理
        DynamicGI.UpdateEnvironment();   // 实时更新环境 GI
    }
}

注意:适用于静态场景;烘焙时间长(大场景小时级)。

2. Realtime GI(实时 GI)

原理:运行时计算间接光,动态响应光源变化。

设置

  • Lighting > Realtime Global Illumination = On
  • 使用 Enlighten(实时 GI 系统)

代码示例

using UnityEngine.Experimental.GlobalIllumination;

public class RealtimeGIController : MonoBehaviour
{
    void Update()
    {
        // 动态光源变化后更新
        if (Input.GetKeyDown(KeyCode.G))
        {
            DynamicGI.UpdateEnvironment();
            Debug.Log("实时 GI 更新");
        }
    }
}

注意:开销高(CPU/GPU);移动端禁用。

3. Mixed GI(混合 GI)

原理:静态光源烘焙,动态光源实时。

设置

  • Light > Mode = Mixed
  • Lighting > Mixed Lighting = Subtractive/Shadowmask

代码示例

public class MixedGILight : MonoBehaviour
{
    public Light dynamicLight;

    void Start()
    {
        dynamicLight.bakingOutput.mixedLightingMode = MixedLightingMode.Shadowmask;
    }
}

注意:平衡性能/质量;需要 Light Probes 辅助动态物体。

4. Light Probes 与 Reflection Probes

Light Probes:采样 GI 到动态物体。

  • 放置:Window > Rendering > Light Probe Group
  • 代码:
  public class ProbePlacer : MonoBehaviour
  {
      void Start()
      {
          LightProbeGroup group = gameObject.AddComponent<LightProbeGroup>();
          group.probePositions = new Vector3[] { Vector3.zero, Vector3.up * 2f };  // 动态放置
      }
  }

Reflection Probes:实时/烘焙反射。

  • 类型:Baked/Realtime
  • 设置:Reflection Probe > Refresh Mode = On Awake/Every Frame

性能监控与最佳实践

5. 监控工具

using UnityEngine;

public class RenderOptimizerMonitor : MonoBehaviour
{
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.F1))
        {
            LogRenderStats();
        }
    }

    void LogRenderStats()
    {
        Debug.Log($"Draw Calls: {UnityEngine.Rendering.RenderPipelineManager.currentPipeline.drawCallsCount}");
        Debug.Log($"SetPass Calls: {UnityEngine.Rendering.RenderPipelineManager.currentPipeline.setPassCount}");
        Debug.Log($"GI 开销: {Lightmapping.GetLightsDirtyCount()}");  // GI 脏标记
    }
}

6. 最佳实践

  • Batching:静态物体 100% 覆盖;动态 <300 顶点。
  • GI:静态场景 Baked,动态 Mixed + Probes。
  • LOD:LOD Group + Batching 结合。
  • 工具:Frame Debugger(分析 SetPass);Profiler(监控 GI 开销)。
  • 管线选择:URP 移动优化;HDRP 高端 GI。

通过从 Batching 到 GI 的系统优化,可将模型渲染效率提升 2-5 倍,适用于大规模场景。如果需要特定代码扩展,请提供更多细节!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注