Unity 之 一些资源标准、性能优化点整合整理
目录
Unity 之 一些资源标准、性能优化点整合整理
零、总起
一、模型
二、图片
三、音频资源
四、灯光
五、碰撞体
六、font
七、UGUI
八、移动端性能优化心得
零、总起
优化思路:
1)和美术指定好相关资源的规范
2)代码框架,合理的管理资源、多线程使用、对象池的使用、算法的优化、一些API 尽量不要在 Update 中频繁使用、UGUI开发规则 等在代码开发中的规范
3)最后,一起应用开发完之后,在使用 profiler 、frame debugger 在最性能分析,针对之前未能顾忌到的点在做优化
性能分析工具:
1)Unity : Profiler、FrameDebugger、PhysicalDebugger
2) Android Studio 、IOS XCode
3)第三方:UWA 等
一、模型
关键:建模原点人物脚底,其他根据情况物体中心,移动端建议面数 1500 面以下,同屏控制50000 以下,剔除断点和孤立点,根据场景,可以使用 遮挡剔除、LOD 技术;
1、所有角色模型最好站立在原点。没有特定要求下,必须以物体对象中心为轴心。
2、面数的控制。移动设备每个网格模型控制在300-1500个多边形将会达到比较好的效果。但是、如果游戏中任意时刻内屏幕上出现了大量的角色,那么就应该降低每个角色的面数。
一般情况:正常单个物体控制在1000个面以下,整个屏幕应控制在7500个面以下。所有物体不超过20000个三角面。
3、整理模型文件,仔细检查模型文件,尽量做到最大优化,看不到的地方不需要的面要删除,合并断开的顶点,移除孤立的顶点,注意模型的命名规范。模型给绑定之前必须做一次重置变换。
4、可以复制的物体尽量复制。如果一个1000面的物体,烘焙好之后复制出去100个,那么他所消耗的资源基本和一个物体消耗的资源一样多。
5、根据情况,可以使用 遮挡剔除、LOD 技术
6、大场景尽量建成一个模型,一个材质,方便合批处理
7、多个单开模型,公用材质,可以 mesh 合并,方便合批,减少 drawcall
二、图片
关键:移动端尺寸 1024 及以下,关闭不必要的读写功能,UI中关闭 mipmap,模型中可根据情况开启 mipmap,使用图片压缩工具在合适压缩原图,合理使用图集进行合批处理,没有alpha 通道就用 jpg,需要alpha 才用 png
1、贴图文件尺寸须为2的N次方 (8、16、32、64、128、256、512、1024)最大贴图尺寸不能超过1024x1024,特殊情况下尺寸可在这些范围内做调整。
2、关闭不必要的 Read/Write Enabled;
默认情况下,纹理被加载到内存,提交给 GPU 时复制一份到显存中,内存中这一份会被删除掉。如果你勾选了 Read/Write Eanbled 选项,那么对应纹理的内存将不会被删除,你可以通过 Texture.GetPixels
和 Texture.SetPixels
等 API 进行读写,导致的问题是额外多一倍的内存。
3、根据情况关闭不必要的 Generate Mip Maps;
- 勾选时会生成多级渐进纹理 Mip Map,以适应三线性采样,解决纹理被映射到尺寸更小的表面造成摩尔纹的问题。多余1/3内存。
- 建议
1)UI 纹理应该关闭 ;2)其它纹理看情况,例如可能会出现在摄像机很远的模型的贴图,可以勾选,以获得在距离摄像机很远时较好的显示效果。
4、合理使用图集 ,sprite packer,texture packer (TexturePacker - Create Sprite Sheets for your game!)
5、没有alpha 通道就用 jpg,需要alpha 才用 png
三、音频资源
1、短音频 使用 wav,长背景乐使用 压缩的MP3;
如果使用任何压缩格式(如 MP3 或 Vorbis),Unity 会将其解压并在构建时重新压缩。这样会导致两个有损通道,从而降低最终质量。
2、load type ,小剪辑 (< 200 kb 短音频) 应采用 Decompress on Load。将声音解压缩为原始 16 位PCM 音频数据,会导致 CPU 开销和内存占用,因此,这仅适用于短声音。
中等剪辑 (>= 200 kb 长音频) 应保持为 Compressed in Memory。
3、实现静音按钮时,不要只是将音量设置为 0。可以销毁 AudioSource 组件,从而将其从内存中卸载,这样,播放器不需要过于频繁地切换开关。
4、合理 控制 AudioSource 组件,可以使用对象池技术,合理控制数量
四、灯光
1、控制实时光的数量
2、使用 光照贴图 lightmap
3、阴影也占用较大性能,取消不必要的阴影接收和投射
五、碰撞体
1、简化碰撞体;尽量少用 Mesh Collider 作为碰撞体
2、在 FixedUpdate 中移动物理体
3、Project Settings 中的默认 Fixed Timestep 是 0.02 (50 Hz)。根据目标帧率对此进行更改(例如,对 30 fps 设置为 0.03)。
否则,如果帧率在运行时下降,也就是说 Unity 每帧都多次调用 FixedUpdate,可能会因物理内容过多而造成 CPU 性能问题。
4、使用 physical debugger 实现可视化
六、font
1、字体库的必要裁剪、留下常用的字体,去除不必要的字体
七、UGUI
1、动静分离。canvas 和 子 canvas ,注意父子canvas 不会一起合批处理
如果是包含成千上万个元素的大型画布,更新单个 UI 元素就必须更新整个画布,这可能会造成 CPU 尖峰。
利用 UGUI 的功能可以支持多个画布。根据 UI 元素的更新频率要求,划分这些元素。将静态 UI 元素保留在单独的画布上,将同时更新的动态元素保留在较小的子画布上。
确保每个画布中的 UI 元素都有相同的 Z 值、材质和纹理。
2、限制GraphicRaycaster 和禁用Raycast Target
输入事件(如屏上触摸或单击)需要 GraphicRaycaster 组件。它只是循环处理屏幕上的每个输入点,检查它是否在 UI 的 RectTransform 之内。
从层级视图的顶层画布中移除默认的 GraphicRaycaster。只向需要交互的各元素(按钮、滚动矩形等)添加 GraphicRaycaster。
另外,在所有不需要 Raycast Target 的 UI 文本和图像上将其禁用。如果是包含很多元素的复杂 UI,所有这些小更改都可以减少不必要的计算。
3、避免使用布局组 layout
布局组的更新很低效,应少量使用。如果内容是动态的,应完全避免不用,而是使用锚点进行比例布局。或者,创建自定义代码,在Layout Group 组件设置 UI 之后,将该组件禁用。
如果动态元素确实需要使用布局组(水平、垂直、网格),应避免嵌套它们,从而改善性能。
4、大型列表和网格视图开销很大。例如 scrollview 可以重复使用其中的item
如果需要创建大型列表或网格视图(如包含成百上千项目的物品栏屏幕),可以考虑重复使用较小的 UI 元素池,而不是为每个项目都创建 UI 元素。
5、避免大量使用重叠元素
对大量 UI 元素(如卡牌游戏中堆叠的卡牌)分层会造成过度绘制。自定义代码在运行时将分层元素合并到更少的元素和批次中。
6、使用全屏UI 时,隐藏其他全部内容,看不懂场景的时候,必要的使用禁用 3D 场景渲染
如果暂停屏幕或者启动屏幕遮住场景中的其他全部内容,则禁用摄像机对 3D 场景的渲染。同样,禁用隐藏在顶层画布之后的所有背景画布元素。
由于不需要以 60 fps 的帧率进行更新,可以考虑在全屏 UI 过程中降低 Application.targetFrameRate。
将摄像机分配给世界空间画布和摄像机空间画布
将 Event 或 Render Camera 字段留空会使 Unity 填充 Camera.main,这会导致不必要的开销。
尽可能使画布 RenderMode 采用 Screen Space - Overlay,这样就不需要摄像机。
八、移动端性能优化心得
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.
- 做好物件、树、角色的LOD.
- 避免使用RenderWithShader类方式来定制DepthTexture,可以考虑Camera的 public void SetTargetBuffers(RenderBuffer colorBuffer, RenderBuffer depthBuffer);进行优化.
- 检查Shader的VertexInput 和 VertexOutput是否存在冗余数据.如:顶点色、多套UV.
- 警惕项目里非必要的双面材质,对于需要局部双面的地方通过加面解决.
- Shader里使用fixed、half代替float,理论上除position、uv、一些涉及depth相关计算使用float外,其他都应该使用fixed(主要是颜色值)、half.
- 对于角色皮肤这种不是特别明显的效果,考虑使用预积分这种低成本的方案.
- 对于frag里的计算过程,如果可以抽出来放到CPU应用层、顶点阶段的优先放这里计算. 需要注意放到顶点阶段引起的平滑过渡问题. 如: eyeVec导致高光过渡问题.
- 镜面反射类效果避免使用反射相机+RT的实现,考虑使用SSR、CubeMap类实现.
- 避免使用实时阴影,如若使用要合理控制下分辨率和阴影距离. 考虑使用Projector.
- 使用统一的后处理框架代替多个Image Effect,可以共用模糊函数,减少blit操作. 另外Unity自带的Postprocessing V2 支持Volume,性能还是不错的.
- Shader里避免使用分支、循环,sin、tan、pow、log等复杂数学运算.
- Unity自带的遮挡剔除因为CPU消耗和内存占用较高,加之不能Instancing,不太适合移动平台,可以考虑静态预计算(缺点是不支持动态物体)、Hi-Z等优化方案.
- 减少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节点的数量,最好支持工具监控.
参考文献:文章来源:https://www.toymoban.com/news/detail-454099.html
1、移动游戏优化指南 | Unity 中文课堂文章来源地址https://www.toymoban.com/news/detail-454099.html
到了这里,关于Unity 之 一些资源标准、性能优化点整合整理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!