Unity GPU Instancing vs Static Batch

概述

对于大批量重复物体优化时候有两个技术会涉及到. 一个是GPU Instancing一个是Static Batch

  • GPU Instancing:实现方式就如同其名字,用GPU直接渲染mesh,跳过了CPU上传部分
  • Static Batch:将一组mesh合并一个大的mesh一次性发给GPU

GPU Instancing

自动

在Material中Enable以后,运行时会自动尝试GPU Instancing. 注意 StaticBatch的优先级会高于GPU Instancing.

在相应的Prefab中会看到Warning

Custom Shader

Unity的Surface Shader是默认支持GPU Instancing的.但是vertex fragment Shader需要一些额外的步骤

  • 指定 #pragma multi_compile_instancing
  • a2v 中加入 UNITY_VERTEX_INPUT_INSTANCE_ID
  • vert 中设置 UNITY_SETUP_INSTANCE_ID(v);

具体的可以参考 Adding instancing to vertex and fragment Shaders章节

手动

手动的话需要自己调用Graphics.DrawMeshInstanced进行渲染. 函数使用不复杂 国内有许多文章都做过”测试”. 手动调用复杂的地方在于物体的剔除部分.
一但使用这个函数Instance对象后,Unity不负责剔除.所以需要自己控制物体的可见性.

Y2B上有人做了一个Demo演示 但是没有给出相应的代码和插件

Jietu20190225-060845-HD

CSDN上看到有一篇文章涉及到相关问题.

并且给出了测试结果.

其实这个结果也是预料之内的. Static Batch是合并mesh上传,所以当mesh量过去大时候肯定会出现瓶颈

API有提到

sometimes you have to sacrifice rendering performance by avoiding static batching for some GameObjects to keep a smaller memory footprint. For example, marking trees as static in a dense forest level can have serious memory impact.

Static Batch

对于场景上的物体可以直接设置Static标记即可

StaticBatchingUtility.Combine

对于后放置的Prefab,需要使用StaticBatchingUtility.Combine手动进行Combine才可以进行Batch.

比如像我现在的场景结构就是一个空的Scene,在run time时候才知道需要加载的哪张地图,从而去load相应的Prefab.

这样即使Prefab内部是标记为Static的了,通过Instance放置到场景上后仍旧不会被StaticCombine.

1
2
var map = Instantiate(MapPrefabReq.asset as GameObject);
StaticBatchingUtility.Combine(map);

其内部实现

也可以看出StaticBatch的逻辑是合并Mesh

性能对比

场景裸跑

开启GPU Instancing


开启Static Batch


当前项目来说 Static Batch Win 😂

坚持原创技术分享,您的支持将鼓励我继续创作!