1.DrawCall优化
1-1:Drall Call Batching (批处理) 静态批处理:场景中所有的静态物体勾选static 动态批处理:unity中自动处理。(动态合批处理动态的GameObjects的每个顶点都有一定的开销,因此动态合批处理仅应用于包含不超过900个顶点和不超过300个顶点的网格。
如果shader中使用Vertex Position, Normal和single UV,可以批量处理最多300个顶点,而如果shader中使用Vertex Position, Normal, UV0, UV1和Tangent,则只能使用180个顶点。)
1-2:遮挡剔除
方案难点:物体必须细分,按类型,或者种类。大小需自己在具体项目尝试,达到最优化的尺寸。
1-3:网格合并,图集合并。(一般不能与2共用,会产生大物体被剔除的问题)
1-4:LOD
LOD是Level Of Detais 的简称,多细节层次。根据摄像机距离显示不同精度的模型。
使用LOD也能使远景更平滑。不会有明显的锯齿
消耗内存来缓解渲染压力。
1-5:MipMap
根据摄像机距离的远近,选择使用不同精度的贴图。
消耗内存来缓解渲染压力。
1-6:Gpu Instancing
1-7:Gpu绘制模型动画方案(GPU-SkinRender)
1-8:减少使用实时光,使用光照贴图(lighing Map)
2.GPU优化
2-1:OverDrall优化(主要优化UI相关的OverDrall):使用SRP定制特定的渲染顺序。
2-2:选择图片的合适MiniMap等级。
3.CPU优化
3-1:优化GC,降低GC的触发频率。
把一些能重复利用的变量做成全局变量。减少new类,list等的操作,多重用list。Unity的物理相关的优化也是用的这些原理。
3-2:unity的Resources.UnloadUnusedAssets()要尽量减少触发频率,会在单次时间内找到所有UnusedAssets,把所以未使用的资源在单次完成卸载。考虑使用Resources.UnloadAsset()把大量的卸载时间平摊到单个资源的单次卸载。这样能有效果的解决调用时间过长的问题。
3-3:使用Shader variants来控制变体的加载。可以优化CPU卡顿问题
3-4:动画精度的优化:
降低动画的数据精度,去除动画里不需要的大小缩放曲线。可以借助工具
3-4:优化堆内存分配:
string的+操作每次都会产生垃圾,请用StringBuilder代替
GameObject.name和GameObject.tag同样每次调用都会产生新的string,当检查是否相等时请使用
GameObject.CompareTag()代替,它不会产生垃圾;
尽量避免装箱拆箱
3-5:在Unity中,如果对Renderer类型调用.material和.materials,那么Unity就会生成新的材质球实例。其主要影响如下:
通过.material,创建材质实例,并修改属性的方式实现多样的渲染效果,时间开销会较高。这里可以参见《使用MaterialPropertyBlock来替换Material属性操作》。
使用相同Shader,但因为Material实例不同的GameObject,所以无法进行合批,导致DrawCall增加,变相造成了CPU耗时的增加。
每次对新的GameObject的Renderer调用.material,都会生成一个新的Material实例,且GameObject销毁后,Material实例无法自动销毁,这会对资源管理造成一定的成本,想要处理的话就需要手动调用“OnloadUnusedAssets”来卸载,但这样就造成了性能开销;管理不好可能会造成材质球大量冗余甚至泄露,极端情况下甚至会导致过高的内存。
建议通过主动MaterialPropertyBlock的方式修改材质属性,或者人为对有限个材质实例进行管理,效果相同的物体通过sharedMaterial来共用材质实例。
4.内存优化
4-1:内存溢出
排查是否有图片shader等的资源相关的冗余。从资源打包方面排查,再到资源管理与加载的方案检查。是否有过渡使用缓存的资源。
4-2:ShaderLab内存占用
4-2.1一般是Shader编译产生的变体内存占用。优化Shader的变体量。
尽量减少shader_feature和#pragma multi_compile等关键字,减小解析耗时,同时减少shader varaints(shader变体)数量,从而减少内存占用。
4-2.2直接去除Shader中的Fallback选项。对于使用Mobile Shader的项目,可以尝试直接将其Fallback去掉大幅降低keyword数量。
网友评论