版本记录
2020-1-2 | 0.1 | 文档初始版本 | 李俊 |
目的
- 加速场景加载,减少loading时间
- 提升场景渲染效率
概念
- 动态合批
- 接口
public void CombineMeshes(CombineInstance[] combine, bool mergeSubMeshes, bool useMatrices); - 核心代码
- 接口
foreach (var subItem in itemValue)
{
CombineInstance combine = new CombineInstance();
ReanderData matReanderData = subItem.Value;
combine.mesh = matReanderData._MeshFilter.sharedMesh;
combine.transform = matReanderData._MeshFilter.transform.localToWorldMatrix;
combines[index] = combine;
index++;
if (combineData == null)
{
combineData = matReanderData;
}
delList.Add(matReanderData._MeshFilter.gameObject);
if(maxValue < matReanderData.scaleInLightmap)
{
maxValue = matReanderData.scaleInLightmap;
}
}
Mesh newMesh = new Mesh();
newMesh.CombineMeshes(combines, true, true);
newMesh.name = combineData._Material.name;
- 静态合批
- 接口
static public void Combine (UnityEngine.GameObject staticBatchRoot, bool combineOnlyStatic) - 静态合批源代码CombineForStaticBatching.csMeshSubsetCombineUtility.cs
- 核心代码
- 接口
private void CombineObj( GameObject obj )
{
Log.Sys("Combine Scene", obj.name);
var anis = obj.GetComponentsInChildren<Animator>();
if (anis.Length > 0)
{
var meshRenders = obj.GetComponentsInChildren<MeshRenderer>();
var gos = new List<GameObject>();
var waterlayer = LayerMask.NameToLayer("Water");
for (int i = 0; i < meshRenders.Length; i++)
{
var go = meshRenders[i].gameObject;
if (go.layer != waterlayer)
{
var isHaveAniP = go.transform.parent.GetComponent<Animator>();
var isHaveAni = go.transform.GetComponent<Animator>();
if (isHaveAniP == null && isHaveAni == null)
gos.Add(go);
}
}
StaticBatchingUtility.Combine(gos.ToArray(), obj);
}
else
StaticBatchingUtility.Combine(obj);
}
原理
- 把场景节点分成必需部分和分块
- 必需部分加载完成,即认为场景加载完成
- 必需部分保存成1个prefab,每个块保存成prefab
- 加载场景时,低优先级加载块prefab,只加载不卸载
制作细节
- _min 表示该节点下不再拆分,即所有子节点只会在同一个块prefab下
- 默认都是可以分块的,必需部分需要在always节点下
合批方案
无
完全依赖运行时instance合批,- 缺点:
- 默认instance合批,不支持lightmap, 需要额外开发instance合批,并且需要大量修改配套的shader
- 相同材质,不同模型的,无法合批
- 优点:
- 不需要生成额外的模型资源,加载友好
- 跨块的也可以提升性能
- 缺点:
动态合批
bake时,把所有材质球一样的模型合并- 缺点:
- 需要重新烘焙,耗时比较长
- 生成新的模型资源,加载不友好
- 烘焙效果可能和原来有差异,因为烘焙参数
- 跨块无法合批
- 优点
- 效率最优
- 可以处理不同模型,相同材质
- 兼容性好
- 开发量相对instance方式小很多
- 缺点:
静态合批
bake时,把每个块内静态合批,必需部分静态合批- 缺点:
- 需要生成大的mesh,对加载最不友好
- 无法处理跨块的合批
- 多场景模式下,会有额外的问题
- 优点:
- 不需要重新烘焙
- 可以处理不同模型,相同材质
- 开发量相对instance小很多
- 缺点: