|
前言
整天在讲性能优化,今天学习了一下课程,发现我一无所知 以下内容是 Unity官方的 OptimizeYourMobileGamePerformance 电子书的阅读笔记
1. Profiling
使用时间轴视图来确定您是受 CPU 限制还是受 GPU 限制。
可以使用Unity自带的Profiling定位是CPU瓶颈还是GPU瓶颈
- 如果您看到Gfx.WaitForCommands标记,则表示渲染线程已准备好,但您可能正在等待主线程上的瓶颈。
- 如果你经常遇到Gfx.WaitForPresent,这意味着主线程已经准备好但正在等待 GPU 呈现帧。
Profiling分析方法1:在优化项目中的任何内容之前,请保存 Profiler.data文件。实施您的更改并比较修改前后保存的.data 。依靠这个循环来提高性能:分析、优化和比较。然后,冲洗并重复。
Profiling分析方法2:Profile Analyzer
2. Memory
Unity 对用户生成的代码和脚本采用自动内存管理。
- 小块数据,如值类型的局部变量,被分配到堆栈中。
- 更大的数据和更长期的存储被分配给托管堆。
垃圾收集器定期识别和释放未使用的堆内存。虽然这会自动运行,但检查堆中所有对象的过程可能会导致游戏卡顿或运行缓慢。
优化内存使用意味着要注意何时分配和释放堆内存,以及如何将垃圾收集的影响降至最低。有关详细信息,请参阅了解托管堆。
内存分析工具:Memory Profiler
3. Adaptive Performance
这个插件,在包管理器可以下载到,主要用来做不同机型的兼容
其实代码也都能写,就是工具造好轮子了,不用重复造轮子 教程:Code Lab | Samsung Developers
Unity文档:Using Adaptive Performance samples
功能:
- 自适应FPS
- 自适应质量设置
- 提供模拟器
- 通过识别设备性能状态和发热趋势,可以实时调整游戏性能和质量设置。
例子:
例子
4. Programming and code architecture(编程和代码架构优化)
了解 Unity PlayerLoop
脚本生命周期流程图
删除调试日志语句
日志语句(尤其是在Update、LateUpdate或FixedUpdate 中)可能会降低性能。在进行构建之前禁用您的日
在Player Settings中禁用ENABLE_LOG预处理器,您的所有Log语句都会一举消失。
使用哈希值而不是字符串参数
Unity 在内部不使用字符串名称来处理 Animator、Material 和 Shader 属性。为了速度,所有属性名称都被散列到属性 ID 中,这些 ID 实际上用于对属性进行寻址。
在 Animator、Material 或 Shader 上使用 Set 或 Get 方法时,利用整数值方法而不是字符串值方法。字符串方法只需执行字符串散列,然后将散列后的 ID 转发给整数值方法。
使用Animator.StringToHash作为 Animator 属性名称,使用Shader.PropertyToID作为材质和着色器属性名称。
举个例子:比如 animator.SetTrigger("h_moveDir"); rider会提醒用静态int去优化: private static readonly int s_HMoveDir = Animator.StringToHash("h_moveDir");
animator.SetTrigger(s_HMoveDir);
选择正确的数据结构
Collections and Data Structures
5. Project configuration
Avoid large hierarchies 避免预制节点太多
节点太多会消耗引擎检查节点的CPU时间
视频:Unite Berlin 2018 - Unity's Evolving Best Practices Transform once, not twice
如果需要同时设置位置和旋转,可以用Transform.SetPositionAndRotation 接口,避免访问transform2次
比如生成GameObject,并初始化的时候,可以直接用GameObject.Instantiate(prefab, parent, position, rotation);减少Transform的多次访问 6. Assets
Arm 和 Unity 联合推出:适用于移动应用程序的 3D 美术优化
Import textures correctly
纹理占用的内存非常多,所以正确的导入设置非常重要
- 尽可能减小最大尺寸
- Use powers of two (POT):纹理尺寸最好是2的次方幂,这样才有使用(PVRCT or ETC 2)压缩纹理
- 打图集:Unity SpriteAtlas 或者 Texture Packer
- 关闭Read/Write选项:开启会创建一份CPU和GPU可访问的内存备份
- 关闭MipMap:很多2d的纹理不需要mipmap
- 压缩格式:Recommended, default, and supported texture formats, by platform
Adjust mesh import settings
- Compress the mesh
- Disable Read/Write
- Disable rigs and BlendShapes
- Disable normals and tangents, if possible
Use the Addressable Asset System
7. Graphics and GPU optimization
Disable shadows
8. User Interface(UI)
- 动静分离
- 隐藏不可见元素
- 需要GraphicRaycaster再添加,需要Raycast Target 再勾选
- Layout Groups 是会一直update的,可以自定义组件,在排序后disable这个组件
- 循环复用列表:GitHub - boonyifei/ScrollList: Optimizing the scroll list
9. Audio
- 勾选force to mono(单声道):多声道音频在运行时很有可能被平衡成单声道
- 使用未压缩的wav格式:使用MP3、Vorbis,Unity会先解压缩,然后build的时候又要再压缩一次,造成2次有损传递,最后降低音质
选择合适的Load Type
- < 200 kb:Decompress on Load
- >= 200 kb:Compressed in Memory
- background music:Streaming,不然整个资源会直接加载到内存
Destory 那些没有在用的声音资源
10. Animation
Use generic VS humanoid rigs
- 导入模型,Unity默认使用 Generic Rig ,但是开发者通常会给他转成 Humanoid Rig
- Humanoid Rig 会比 Generic Rig 多耗费30%-50%的CPU,用来计算IK和动画重定向,如果你不需要这些功能的话,最好还是用Generic Rig
避免滥用Animation
Animator是主要设计来给人形角色用的组件
对于一些简单的动画,可以用DOTween实现,尽量不要用Animation 11. Physics
Optimize your settings
- 勾选 Project Settings > Player > Prebake Collision Meshes
- 尽可能简化你的碰撞矩阵:Project Settings > Physics > Layer Collision Matrix
- Disable Auto Sync Transforms and enable Reuse Collision Callbacks.
- 移动一个挂有Rigidbody的对象,用MovePosition or AddForceMove,直接访问Transform会导致物理时间的重计算,然后如果需要在update里刷新的话,最好是在FixedUpdate.(具体原理没写)
- Window > Analysis > Physics Debugger,定位物理问题
12. Workflow and collaboration
拆分大场景
跟拆大预制一样,拆分场景,然后用附加的方式添加场景(LoadSceneMode.Additive) 13. Unity Integrated Success
14. Conclusion
完整看下来,这本书就是Unity的插件一览会,插件安利书,虽然有提到一些有用的,但是没讲原理,不过可以自行百度就是了,好的一点是,整理了个优化的框架,以后有新的东西,可以往里面填。
<hr/>Unity性能优化:可以从以下4个方面去讲:CPU、GPU、内存、显存
性能优化和图形硬件的关系
CPU和GPU的交互
- 代码在CPU运行,从内存中获取数据
- 显卡通过PCI总线插在主板上,
面试经典题1:性能调优你们都怎么做的?
定位瓶颈、理解问题、解决问题、掌握技巧 定位瓶颈
①CPU瓶颈:
打开Unity Profiler窗口,查看耗时长的函数是否正常,是否有GC Alloc,
字符串拼接用StringBuilder
序列化与反序列化(Json、XML、PB)
GetComponents、Input.Touches、Mesh.vertices等接口返回的是内存的拷贝,注意这些Get系列的函数
Debug.Log,Warning
Lambda表达式、匿名函数、Linq
Camera.main:GameObject.FindObjectWithTag(&#34;MainCamera&#34;)
Physics.RaycastAll==>Physics.RaycastNonAlloc ②GPU性能瓶颈:
States窗口,看Batches(DrawCall合批次数)、SetPassCall(CPU往GPU发送命令数量),3D模型、UGUI ③其他:物理
面试经典题2:UI卡顿你们是怎么解决的?
Canvas优化要点
- 动静分离:UI界面很复杂的话,要划分更多的子Canvas,因为一个Canvas下的所有元素都是合成在一个mesh进行渲染的,过大的mesh更新时开销很大,拆分频繁变化的部分自成一个Canvas,这样刷新的时候就不用刷新不变化的部分,减少性能消耗
- 一个面板的UI资源放同一个图集
- 大预制拆分成子面板
OverDraw(GPU)
- 造成GPU性能瓶颈原因:复杂的顶点或者像素计算、OverDraw(光栅化阶段填充像素过多)
- 解决方案:禁用不可见UI、不要使用空Image==》EmptyRaycast
- 少用LayoutGroup或者ContentSizeFitter==》自己写算法自己算
- Layout原理:遍历SetDirty对象会消耗性能
面试经典题3:模型优化有什么好的办法?
- 蒙皮网格动画==》顶点动画【空间换时间】
- Animator LOD【远处动画降帧】
- Animation Instancing【比如一堆一样模型的士兵、花草树木等】
- 慎用MeshCollider【低模或者改用胶囊体】
- 静态合批:Mesh.CombineMesh()【空间换时间】
- 动态合批:骨骼蒙皮、GPU Skinning
- 地形:Terrian==>Mesh、MMO分区域地图、动态加载卸载、接缝处理
- 纹理贴图:Mipmap、三线性插值、注意半透明优化
- 定位Shader瓶颈
- 关闭不用的碰撞矩阵
- 定时主动GC
- 不用的资源要销毁或释放,需要的资源要缓存
- 尽量异步加载、防止阻塞
面试经典题4:UI优化:文本优化:TextMesh Pro
参考
CPU与GPU协同工作_豌豆射手的专栏-CSDN博客
Unity_eBook_OptimizeYourMobileGamePerformance_V6_May2021.pdf
Optimize your mobile game performance: Tips on profiling, memory, and code architecture from Unity’s top engineers | Unity Blog |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|