Unity性能优化篇(十四) 其他优化细节以及UPR优化分析器

代码优化:

  1. 使用AssetBundle作为资源加载方案。

而且经常一起使用的资源可以打在同一个AssetBundle包中。尽量避免同一个资源被打包进多个AB包中。压缩方式尽量使用LZ4,少用或不要用LZMA的压缩方式。如果确定后续开发不会升级Unity版本,则可以尝试启用打包选项BuildAssetBundleOption.DisableWriteType,这样TypeTree信息不会被打到AB包中,可以极大减小包体大小以及运行加载时的内存开销。

  1. 使用AssetBundle或者Addressables加载的资源,如果不使用,要记得卸载它们,否则会造成内存泄漏。

不用的资源要释放掉,不用的引用类型的变量也要赋值为null,不要让它们一直占着内存中。

  1. 加载资源时尽量使用异步加载。

  2. 频繁创建和销毁对象,可以使用对象池。

  3. 切换场景时,旧的场景要释放掉 ,不用的资源也可以考虑释放掉,也可以考虑用System.GC.Collect来进行一次垃圾回收。

  4. 锁定游戏的帧率 。帧率为30,游戏会明显卡顿,但是对于手游来说,消耗手机的电量比较少。帧率为45,游戏有一点点卡,但还凑合,消耗电量中等。帧率为60,游戏很流畅,但消耗手机的电量会比较多。可以用Application.targetFrameRate来锁定帧率,也可以用UnityEngine.Rendering命名空间中的OnDemandRendering.renderFrameInterval来锁定帧率。

7.尽量少用foreach语句,可以改为for语句 。因为每次使用foreach语句会造成微量的内存垃圾。

8.要判断GameObject型对象.tag是不是某个标签,使用GameObject型对象.CompareTag方法会更高效。

  1. 尽量少用GameObject.Find方法和Object.FindObjectOfType方法来查找游戏对象,可以提前把要查找的游戏对象存储在变量、列表、字典等容器中,方便查找。也可以用GameObject.FindGameObjectWithTag方法来查找游戏对象。

  2. 在UI显示字符串的时候,如果一些内容是固定的,我们可以把它拆分开来,这样可以减少使用+号来拼接的次数,减少内存垃圾的产生。例如"杀敌数:999",其中"杀敌数:"是固定的,冒号后面的数字才是会变的,那么我们可以用两个Text组件分别记录它们,改变的时候只改变冒号后面的数字。

11.频繁对字符串赋新的值,或者频繁拼接字符串的时候,可以使用StringBuilder代替string

  1. 如果要频繁操作某脚本,不要每次都用GetComponent方法来获取这些脚本。可以用一个变量存储起获得的这个脚本,之后要访问它,就直接访问这个变量即可。也可以考虑在生命周期方法Awake或者Start中声明变量来存储,之后访问这个变量即可。

13.尽量少用正则表达式。虽然正则表达式的形式看上去比较简便,但是使用它会造成一定的性能消耗,且会产生内存垃圾。

14.尽量少用LINQ语法,因为每次使用LINQ都会产生一定量的内存垃圾。

15.尽量少用Camera.main来访问主摄像机,因为每次访问它,实际上Unity都是从场景中查找它的。可以声明一个变量存储它,在生命周期方法Awake或Start中获取主摄像机的应用。

16.在Animator、Shader中使用Get方法和Set方法时,不传入字符串作为参数,而是传入哈希值。例如Animator组件可以使用Animator.StringToHash方法获得指定字符串的哈希值,再把它作为参数传入Animator组件的Get方法或Set方法中进行使用。例如Shader,则可以用Shader.PropertyToID方法来获取指定属性的ID

17.使用非分配物理API。例如使用Physics.RaycastNonAlloc方法代替Physics.RaycastAll方法,使用Physics.SphereCastNonAlloc方法代替Physics.SphereCastAll方法,以此类推。Physics2D类也有类似的方法。

18.一般情况下,整数的数学运算比浮点数的数学运算效率高,浮点数的数学运算比矢量的数学运算效率高。可以灵活运用数学的加法交换律、加法结合律、乘法交换律、乘法结合律,在保证结果不变的前提下,调整运算顺序,减少浮点数的数学运算和矢量的数学运算。

19.使用高效的算法进行计算

20.每次执行Debug.Log来打印信息会消耗极少量的性能,如果要在游戏正式发布之后不执行某些Debug.Log的语句,但又不想把这些代码删掉,则可以使用宏来禁止在游戏正式发布之后执行Deubg.Log的语句。例如使用#if语句或者Conditional特性。

21.尽量减少在生命周期方法Update、FixedUpdate、LateUpdate中的逻辑。其中有些不需要频繁执行的逻辑,可以使用协程或者Invoke方法,每隔指定的秒数执行一次或每隔指定的帧数执行一次。

  1. 尽量避免频繁的装箱拆箱操作。也可以使用泛型,这样就能避免装箱拆箱。但是要注意,Lua热更新对泛型的支持不太好。

23.如果物体身上添加了刚体组件,则尽量用刚体组件的方法来移动它,而不是用Transform类的方法来移动它。

24.如果物体身上添加了CharacterController组件,则尽量用CharacterController组件的方法来移动它,而不是用Transform类的方法来移动它。同理,如果物体身上添加了刚体组件,则应尽量用刚体组件的方法来移动它,而不是用Transform类的方法来移动它。

25.应尽量避免DontDestroyOnLoad中加载的资源过多,因为它在切换场景的时候不会被释放,声明的变量以及加载的资源会一直占用着内存。我们可以考虑把一些资源不用的资源释放掉,需要的时候再加载它。

26.不使用组件可以删掉,这样可以节省一些内存。常见的有AudioSource组件、Animator组件、Animation组件等,如果它们不需要使用,则可以删掉。

27.写一个类继承AssetPostProcessor,然后定义里面特定的方法,以此来自动设置资源导入Unity之后的属性。

28.尽量避免闭包。因为闭包会产生额外的内存开销。

可以使用Unity UPR对整个项目进行性能分析,找出问题后,再手动优化它们。

Unity UPR网址:https://upr.unity.cn/instructions/desktop

其中Unity UPR中的Asset Checker能对本地的整个Unity项目进行性能分析,帮助我们找出问题。

相关推荐
新*2 小时前
从一段 WebSocket 代码聊开:bytes 不是 zlib、binaryType 决定一切,15MB 大消息的零拷贝优化
javascript·python·websocket·性能优化·blob·zlib·arraybuffer
疯华整猫7 小时前
把二十七个 init 从首帧前面搬走:用 Trae 把启动优化钉进 CI
android·性能优化·ai编程
17岁的勇气8 小时前
Unity Shader unity文档学习笔记(二十二):shader变体
笔记·学习·unity
数据库小学妹1 天前
MySQL大字段治理:行溢出机制、覆盖索引与拆表
数据库·mysql·性能优化
贾伟康1 天前
【共创稿事节】HarmonyOS 7.0 Progress进度体系:从接入到生产验证
性能优化·实战·harmonyos·arkts·arkui
寂寞的船1 天前
【Unity知识速递】第10期 Unity GC 零分配实战:从 UnityEngine.Pool 到手动 GC 控制的全链路优化
jvm·unity·c#·游戏引擎·lucene
Martina_03212 天前
AI生成3D场景的霓虹灯一开就糊成光团?用6步检查Emissive、Bloom与曝光
人工智能·3d·ai·自然语言处理·游戏引擎·材质·贴图
疯华整猫2 天前
我用 Trae 把 Android 内存账重算了一遍
android·性能优化·源码
寂寞的船3 天前
【Unity知识速递】第8期 IL2CPP 托管堆内存碎片与原生堆交互机制深度解析
unity·游戏引擎·交互
寂寞的船4 天前
【Unity知识速递】第5期 Unity 6.2 深度解析:AI Assistant 登场,World Space UI 与 Sentis 全面升级
人工智能·ui·unity