zt3ff3n 发表于 2021-12-6 20:01

Unity移动端性能优化总结(持续补充)

本文总结记录我在工作中遇到的一些性能问题及优化技巧和心得,后续会持续更新补充.
箴言

[*]项目前期一定要立好符合产品定位的美术标准!
[*]过早的优化是万恶之源.
3. 不要为了优化而优化.
4. 一定要在真机环境评估美术资源的合理性和性能问题定位.
5. 如果一个模块反复优化来优化去,那就要考虑下重构了.
工具篇
市面上的性能分析工具很,这里列举下我常用的工具和方法

[*]Unity Profiler: 定位性能热点、GC、资源内存占用等.
[*]Unity FrameDebugger: 分析drawcall、渲染流程、排查渲染问题.
[*]RenderDoc: 详细的渲染管线数据分析、分析渲染耗时、逆向.
[*]Intel GPA: 渲染分析、逆向(比较方便选取像素).
[*]XCode: IOS平台详细的性能热点定位、CPU/GPU性能分析、Shader分析、功耗分析.
[*]SnapDragon Profiler: 骁龙处理器详细的CPU/GPU实时参数数据、功耗温度、逆向.
我平时用的最多的还是RenderDoc和XCode. RenderDoc因为可以直接接入到Unity上,使用比较方便,而且可以方便快速的查看渲染管线和渲染耗时统计(虽然这个值不一定很准确,但是对我确定优化方向很有帮助)。


XCode附带的性能分析工具很多,而且它的性能分析数据都非常详尽,对于确定CPU/GPU瓶颈、Shader耗时统计、Shader性能分析都非常有参考价值.



查看各个Shader的耗时



上图可以看出该Shader的Float计算比例很高.





CPU端性能优化

[*]逻辑和表现尽可能分离开,这样逻辑层的更新频率可以适当降低些.
[*]对于一些热点函数,如mmo的实体更新、实例化,使用分帧处理,分摊单帧时间消耗.
[*]做好同屏实体数量、特效数量、距离显隐等优化.
[*]完善日志输出,避免没必要的日志输出,同时警惕日志字符串拼接.
[*]使用骨骼烘焙 + GPUSkinning + Instance 降低CPU蒙皮骨骼消耗和drawcall.
[*]开启模型的Optimize GameObjects减少节点数量和蒙皮更新消耗.
[*]UI拼预制做好动静分离,对于像血条名字这种频繁变动的ui,做好适当的分组.
[*]减少C#和lua的频繁交互,尽量精简两者传递的参数结构.
[*]使用stringbuilder优化字符串拼接的gc问题.
[*]删除非必要的脚本功能函数,特别是Update/LateUpdate类高频执行函数,因为会产生C++到C#层的调用开销. 对于Update里需要用到的组件、节点等提前Cache好.
[*]场景里频繁使用的资源或数据结构做好资源复用和对象池.
[*]对于频繁显示隐藏的UI,可以先移出到屏幕外,如果长时间不显示再进行Deactive.
[*]合理拆分UI图集,区分共用图集和非共用图集,共用图集可以常驻内存,非共用图集优先按功能分类,避免资源冗余.
[*]使用IL2CPP, 编译成C++版本能极大的提升整体性能.
[*]避免直接使用Material.Setxxx/Getxxx 等调用,这些调用会触发材质实例化消耗,可以考虑使用 SharedMaterial / MaterialPropertyBlock代替.
[*]合并Shader里的Uniform变量.

GPU端性能优

[*]合理规划好渲染顺序,避免不必要的overdraw,如:地形(容易被其他物件遮挡)、天空盒放到较后渲染.
[*]分辨率缩放,对于填充率出现瓶颈时,这个是最简单高效的.
[*]避免使用GrabPass抓屏,不是所有硬件都支持,加之数据回拷和没法控制分辨率性能很差,可考虑使用CommandBuffer.blit去优化.
[*]控制好地形的Blend层数,控制在4层以内,考虑到地形一般屏占面积大、贴图采样次数多,对于中低画质考虑不用normalmap.
5.做好物件、树、角色的LOD.
6.使用RGB111110Float代替RGBAHalf作为HDR格式,节省带宽.
7.避免使用RenderWithShader类方式来定制DepthTexture,可以考虑Camera的
public void SetTargetBuffers(RenderBuffer colorBuffer, RenderBuffer depthBuffer);进行优化.
8. 检查Shader的VertexInput 和 VertexOutput是否存在冗余数据.如:顶点色、多套UV.
9. 警惕项目里非必要的双面材质,对于需要局部双面的地方通过加面解决.
10. Shader里使用fixed、half代替float,理论上除position、uv、一些涉及depth相关计算使用float外,其他都应该使用fixed(主要是颜色值)、half.
11. 对于角色皮肤这种不是特别明显的效果,考虑使用预积分这种低成本的方案.
12. 对于frag里的计算过程,如果可以抽出来放到CPU应用层、顶点阶段的优先放这里计算. 需要注意放到顶点阶段引起的平滑过渡问题. 如: eyeVec导致高光过渡问题.
13. 镜面反射类效果避免使用反射相机+RT的实现,考虑使用SSR、CubeMap类实现.
14. 避免使用实时阴影,如若使用要合理控制下分辨率和阴影距离. 考虑使用Projector.
15. 使用统一的后处理框架代替多个Image Effect,可以共用模糊函数,减少blit操作. 另外Unity自带的Postprocessing V2 支持Volume,性能还是不错的.
16. Shader里避免使用分支、循环,sin、tan、pow、log等复杂数学运算.
17. Unity自带的遮挡剔除因为CPU消耗和内存占用较高,加之不能Instancing,不太适合移动平台,可以考虑静态预计算(缺点是不支持动态物体)、Hi-Z等优化方案.
18. 减少alpha test材质的使用,如若使用注意减小面积、控制渲染顺序.

内存优化

[*]警惕配置表的内存占用.
[*]检查ShaderLab内存占用:
[*]避免使用Standard材质,做好相应的variant skip.
[*]排查项目冗余的Shader.
[*]使用shader_feature替代multi_compile,这样只会收集项目里真正使用的变体组合,避免变体翻倍.

[*]检查纹理资源的尺寸、格式、压缩方式、mipmap、Read & Write选项使用是否合理.
[*]检查Mesh资源的Read & Write选项、顶点属性使用是否合理.
[*]代码级别的检查,如Cache预分配空间、容器的Capacity、GC等.
[*]使用Profiler定位下GC,特别是Update类函数里的. 如:字符串拼接、滥用容器等.
[*]合理控制RenderTexture的尺寸.
[*]优化动画Animation的压缩方式、浮点精度、去除里面的Scale曲线数据.
[*]减少场景GameObject节点的数量,最好支持工具监控.

功耗发热优化
按理说上面的CPU、GPU、内存的优化(容易被忽略,内存的使用频率也很影响功耗)也能减轻功耗发热问题,除此之外还有:

[*]控制全屏后处理的使用数量、关键的性能参数、分辨率等.
[*]支持自动省电模式:如当玩家1min没有操作时自动进入省电模式.
常用的省电优化项:

[*]降低FPS.
[*]将分辨率缩放到最低(如1280 * 720)
[*]降低Update / LateUpdate 等高频函数的执行频率.
[*]关闭一些显示效果,如后处理皮肤、bloom、抗锯齿等.
[*]如果开了实时阴影,考虑降低更新频率、调低效果参数等.

上面列的这些大部分都是常规优化,暂时先写这么多,后面想到再写(持续更新!!!)

BlaXuan 发表于 2021-12-6 20:11

总结确实比较详细
页: [1]
查看完整版本: Unity移动端性能优化总结(持续补充)