当前位置:   article > 正文

Unity中的DrawCall_unity drawcall

unity drawcall

一:绘制原理

为了将物体绘制到屏幕上,引擎必须向图像API(例如OpenGL、Direct3D)发送一个DrawCall指令,每一次发送DrawCall指令的过程为一个渲染批次(Batch),而这个过程分为两大部分:设置渲染状态(setPass)和调用DrawCall(Batches),其中设置渲染状态属于比较重的分工,对于加载到游戏中的资源和对象等,CPU需要计算其顶点相关的矩阵,渲染所用的贴图,渲染所用到的材质和shader,渲染所用到的灯光等,如果每个物体的材质和贴图等都不一样,此时CPU的主要工作就是设置这些物体的渲染状态后调用DrawCall,从而造成CPU性能的开销,简单来说也就是CPU向GPU发送指令并由GPU进行绘制


二:DrawCall过多导致的结果

——程序卡顿
——耗电量快
——设备发热


三:什么是批处理?

因为CPU每一次发送DrawCall指令都会造成CPU的性能开销(DrawCall次数越多,CPU进行计算的量越大),而CPU的处理速度比GPU慢多了,所以可以将绘制的压力移交给GPU
Unity可以将一些物体进行合并,从而用一次DrawCall来渲染他们。这一操作,称为批处理
例如渲染一千个三角形,如果把它们按一千个单独的网格进行渲染则需要请求1000次DrawCall,而如果直接渲染一个包含了一千个三角形的网格则只需要请求1次DrawCall,这样减轻了CPU的计算开销在性能上会有很大的提升


四:渲染统计窗口


默认一个空3D工程,会有两个Batches,一个是天空盒,一个是相机
——Batches:相当于DrawCall次数
——Saved by batching:通过批处理节省的DrawCall次数
——SetPass calls:设置渲染状态的次数
只有在相机视野内的会被统计

在Unity中可以通过UnityStats类去查看DrawCall等数据,一般在移动端DrawCall尽量保持在200以下


五:3D场景优化

——静态批处理
静态批处理默认是开启的,Project Setting—Player—Static Batching
将需要静态批处理的物体设置为Static,游戏运行时会自动为它们合批,将所有静态物体的Mesh Filter自动合并成一个新的Mesh
可以使用工具类动态设置合并的对象:StaticBatchingUtility.Combine,这样就不需要勾选Static

注意:
——需要有相同材质,如果不同只会合并mesh,batches还是会增加
——静态合批的最大顶点数是65535,如果顶点数超过了它,Unity就会自动合并出多个Mesh
——运行游戏后合并过的Mesh对象是不可以发生位移的,但是可以移动父物体节点
——打包时会把合并的mesh存储起来,所以需要额外的内存去存储,并且运行时需要加载这个合并后的大Mesh,所以使用时需要注意,例如一个很大场景,使用静态批处理后包体中就会多一份合并的Mesh,运行时也会加载整个大场景的Mesh,但是游戏运行后只有一小部分出现在摄像机内,那么整个大的Mesh都需要参与渲染


——动态批处理
动态批处理默认是关闭的,需要手动开启:Project Setting—Player—Dynamic Batching

条件限制:
——必须使用相同材质(相同材质的物体之间的差别只在于顶点数据不同,可以将顶点数据合并在一起,再一起发送给GPU)
——Mesh不能超过900个顶点(带uv的模型不能超过300个顶点)
——transform的scale属性不能有负值
——多个pass的shader会破坏批处理


——GPU Instancing
GPU Instancing是指使用相同的材质和网格来渲染多个物体,但每个物体的属性(位置、颜色等)不同。这种方式适用于需要大量重复的物体,比如草地、树木等
勾选Material中的属性Enable GPU instacing,只有在支持GPU Instancing的shader才能选择

条件限制:
——必须使用相同网格和相同材质


——SRP Batcher 
只在UPR或SRP项目中有效,带有如MeshRender、TrailRender、LineRender、ParticleSystem、SpriteRender组件的mesh支持合批。带有SkinMeshRender和 布料模拟的mesh是不能合批


——减少实时光照和阴影效果
实时阴影会导致drawcalls大幅上升,建议关闭实时阴影,使用lightmap满足你想要的阴影效果


——代码动态合并网格
静态批处理会增加额外的内存消耗去存储合并后的Mesh,但原先没有用的Mesh仍保留在内存中,所以可以通过代码动态合并网格后将原先的网格销毁或隐藏

  1. using UnityEngine;
  2. /// <summary>
  3. /// 合并网格(挂载到要合并网格所有物体的父物体身上)
  4. /// </summary>
  5. public class CombineMesh : MonoBehaviour
  6. {
  7. private void Start()
  8. {
  9. Combine();
  10. }
  11. /// <summary>
  12. /// 合并网格
  13. /// </summary>
  14. public void Combine()
  15. {
  16. MeshFilter[] filter = GetComponentsInChildren<MeshFilter>();
  17. MeshRenderer[] renderer = GetComponentsInChildren<MeshRenderer>();
  18. Material[] mat = new Material[renderer.Length];
  19. CombineInstance[] combine = new CombineInstance[renderer.Length];
  20. for (int i = 0; i < renderer.Length; i++)
  21. {
  22. mat[i] = renderer[i].sharedMaterial;//获得共享材质
  23. combine[i].mesh = filter[i].sharedMesh;
  24. combine[i].transform = filter[i].transform.localToWorldMatrix;
  25. filter[i].gameObject.SetActive(false);
  26. }
  27. GameObject mesh = new GameObject("CombinedMesh");
  28. mesh.AddComponent<MeshFilter>().mesh.CombineMeshes(combine);
  29. mesh.AddComponent<MeshRenderer>().sharedMaterial = mat[0];
  30. }
  31. }

六:UI优化

UI批处理流程:
——找到所有Canvas,剔除掉alpha=0的Canvas
——对Canvas下所有的元素按照Hierarchy层级面板从上到下(深度优先)分析每个元素的depth(下面会介绍depth的计算规则),这个过程中会剔除掉不渲染的元素(activeSelf为false、空节点、Image等脚本被禁用的节点等)
depth计算规则:
——不显示的ui元素depth为-1,不考虑
——判断元素底部是否还有元素(通过判断mesh网格是否相交),如果没有则depth为0,如果有则判断此元素和底部元素的materialId和textureId是否相同,如果相同则depth等于底部元素depth,如果不同则取底部元素的dpeth值+1
——将所有元素加入到一个ui元素队列中,升序依次按照depth、materialId、textureId、Renderer Order排序,根据得到的队列,判断相邻元素之间的材质和贴图是否相同,只要相同就可以进行合批(注意这里不会对深度值进行判断,即使相邻元素深度值不同,只要满足上述条件也可以进行合批)

——避免多个Canvas
——避免Mask组件
——打图集
——UI元素打断合批必须是有重叠,所以注意不能合批的对象尽量不要重叠
——注意Z轴和旋转的影响(在同一平面就不会影响,也就是180度的倍数),如果在Hierarchy面板中顺序是连续的(面板上可以合批的元素是挨着的),则没影响,如果在Hierarchy面板中顺序不连续则会受到Z轴和旋转的影响

UI渲染顺序:Camera的Depth>Sort Order>Plane Distance(Z轴深度)>面板上的顺序


七:2D Sprite优化

——打图集
——Sorting Layer、Order in Layer、Z轴都会影响

SpriteRenderer渲染顺序:Camera的depth>Z轴深度>Sorting Layer>Order in Layer


八:其他打断批处理的因素

——调用Render.material也会创建一个新的material打断合批,应该使用render.shareMaterial保证材质共享

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/897950
推荐阅读
相关标签
  

闽ICP备14008679号