Unity3D 进阶教程 - 10 渲染优化

概述

入门系列第 19 篇介绍了性能优化的基本概念。本篇专门聚焦 渲染优化,这是游戏性能瓶颈的最常见领域。

渲染优化分为 CPU 端(减少要发送给 GPU 的渲染指令数)和 GPU 端(减少每个像素的计算量)。真正的优化不是盲目降低画质,而是 在保持视觉质量的前提下,最小化 GPU 需要处理的数据量

1. CPU 端优化:减少 Draw Call

Draw Call 是 CPU 向 GPU 发出的渲染命令。关键在于 批处理——让多个物体共享一次 Draw Call。

1.1 静态批处理(Static Batching)

Unity 在构建时将共享相同材质的静态物体合并为一个网格。

1
2
// 物体标记为 Static
// Inspector 右上角 Static 下拉菜单 -> 勾选 Batching Static

要求:

  • 物体必须标记 Batching Static
  • 共享同一材质
  • 位置在运行时不再变化

1.2 动态批处理(Dynamic Batching)

Unity 在运行时将小物体的 Draw Call 合并。限制:顶点数小于 300(移动端)。

1.3 GPU Instancing

适合大量相同物体的渲染(如一群树、子弹、粒子):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class TreeInstancer : MonoBehaviour
{
[SerializeField] private Mesh _mesh;
[SerializeField] private Material _material;
[SerializeField] private int _count = 1000;

private void Start()
{
var matrices = new Matrix4x4[_count];
for (int i = 0; i < _count; i++)
{
matrices[i] = Matrix4x4.TRS(
Random.insideUnitSphere * 50,
Quaternion.Euler(0, Random.Range(0, 360), 0),
Vector3.one * Random.Range(0.8f, 1.2f)
);
}

Graphics.DrawMeshInstanced(_mesh, 0, _material, matrices);
}
}

1.4 SRP Batcher

URP 的核心批处理机制,比静态/动态批处理更高效。默认启用。


2. GPU 端优化

2.1 LOD(细节层次)

物体距离相机越远,使用越简化的模型。

2.2 遮挡剔除(Occlusion Culling)

Unity 自动剔除相机视野外的物体。遮挡剔除进一步剔除被遮挡的对象。

1
2
室内场景:遮挡剔除收益巨大(70% 的物体可能被遮挡)
空旷场景:收益有限

2.3 减少 Overdraw

Overdraw 是同一像素被多次填充的次数。

优化策略:

  • 透明物体尽量减少覆盖面积
  • 粒子使用 Additive 混合模式
  • 使用 Z-Prepass

2.4 纹理优化

1
2
3
4
5
6
7
压缩格式选择:
PC: DXT5(带 Alpha)/ DXT1(无 Alpha)
移动端: ASTC(推荐)

纹理大小控制:
3D 场景纹理:2048x2048 以内
角色纹理:1024x1024 以内

3. 移动端专项优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MobileOptimizer : MonoBehaviour
{
private void Awake()
{
Application.targetFrameRate = 30;
QualitySettings.vSyncCount = 0;

var urpAsset = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
if (urpAsset != null)
{
urpAsset.shadowDistance = 15f;
urpAsset.mainLightShadowCascadesCount = 1;
}
}
}

4. 技术指标参考

目标平台 最大 Draw Call 建议效果
高端 PC 3000+ 全开
高端手机 200-300 关闭动态阴影,Bloom 降低
低端手机 80-150 关闭后处理,阴影距离 <= 15

5. Profiling 技巧

1
2
3
4
5
6
7
8
9
public class RenderStatsGUI : MonoBehaviour
{
private void OnGUI()
{
GUILayout.Label("FPS: " + (1f / Time.smoothDeltaTime).ToString("F1"));
GUILayout.Label("Draw Call: " + UnityEngine.Profiling.Profiler.RenderStats.drawCalls);
GUILayout.Label("三角面: " + UnityEngine.Profiling.Profiler.RenderStats.triangles);
}
}

总结

  • CPU 端:用 SRP Batcher / 静态批处理 / GPU Instancing 减少 Draw Call
  • GPU 端:用 LOD / 遮挡剔除 / 纹理压缩 / 着色器优化 减少像素计算
  • 移动端:锁定 30fps、降低影子距离、控制后处理效果
  • 工具链:Frame Debugger -> Rendering Profiler -> RenderDoc 逐层排查

下一篇将讲解 Profiler 深度分析,学会系统性地定位性能瓶颈。

ByteFisher
分享编程技术 · 记录钓鱼乐趣
扫码关注
▸ 扫码关注 ◂
分享: