性能优化-场景分块

版本记录

日期 版本 说明 作者
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;
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小很多

猜你喜欢

转载自www.cnblogs.com/marcher/p/12161440.html