Unity开发规范

代码

控制频繁调用GC

  1. 控制高频率的内存分配。
  2. 控制大块的内存申请,可能会造成内存的碎片化,如果需要申请,尽可能在刚启动时申请。
  3. 控制容易导致 GC alloc的函数调用
  4. [Mono]控制字符串拼接/ToString/ToArray
  5. [Mono]Boxing(拆装箱操作)/委托/匿名函数
  6. [Mono]Tag/Name/Mesh.Vertices
  7. [Lua]Vector等非基础类型的参数传递

脚本注意事项:

  1. 避免Update LateUpdate等函数频繁的gc alloc
  2. 避免在Update()内GetComponent()
  3. 避免在Update()内FindObjectsOfType()
  4. 避免在Update()里赋值给栈上的数组,会触发堆内存的反复分配
  5. 避免在Update()内使用GameObject.Tag和GameObject.Name,用CompareTag来进行比较
  6. 避免频繁调用alloc-accessors(如Mesh.vertices/normals/uvs、SkinedMeshRenderer.bones),如果一定需要,也尽量缓存起来
  7. 避免频繁调用int.tostring()及其它类型的衍生
  8. 避免OnGUI的调用
  9. 频繁创建和更新的字符串尽量缓存,比如CD时间等
  10. 尽量避免dict.Values操作,直接遍历取Value即可
  11. 用RayCastNoAlloc替换RayCastAll/用yield return null代替yield return 0
  12. 尽量少用lambda,创建带upvalue的lambda对象会产生124B的GC,禁止在Update或for循环中使用
  13. 委托有+=务必要有-=,另外禁止有太长的委托调用链
  14. 禁止通过new的方式实例化MonoBehavior的派生类,否则无法得到引擎的有效管理
  15. 禁止在Update/FixedUpdate/LateUpdate/OnGUI等频繁调用的逻辑中使用携程
  16. 尽量少用Resources.Load加载资源
  17. 禁止使用Invoke("func",1)来实现延时调用
  18. 尽可能避免使用携程。Unity的协程是使用迭代器实现的会分配堆内存
  19. 使用网格导航时,尽可能避免使用Obstacle模拟动态障碍物,否则对CPU的冲击比较大,如有此类需求建议使用碰撞体替代
  20. 禁止在MonoBehavior的派生类中存在被引擎高频调用的空方法,如Update里面没有方法内容就应该删掉
  21. 禁止在MonoBehavior的派生类中存在Awake/Start/OnEnable/OnDestroy等空方法
  22. 必须使用CompareTag接口比较GameObject的Tag。看到Unity源码,在使用CompareTag对比Tag时,是对比int类型。
  23. 尽可能减少UnityEngine.Onject null 比较
  24. 尽量避免使用Relection(反射)
  25. 尽量避免使用可变参数(param object[] args),避免装箱拆箱操作il2cpp中会重载多个方法,导致生成的文件过大)
  26. 禁止没有计算需求的变量赋值或者计算
  27. 简单条件判断尽量使用三目运算符:b?x:y
  28. 注意List等容器常用接口的复杂度,尽量从尾部移除/批量移除(RemoveRange)等
  29. 在频繁查询数据列表时,建议使用HashSet/HashTable 查找时间复杂度低的数据结构,避免使用List
  30. 使用可变长容器时,建议根据预估容器进行初始化
  31. 循环中寻找到适合条件的后应该适时地使用break跳出循环
  32. 尽可能将一些内存占用低但为数众多/功能简单的小对象定义为Struct(结构体)而非Class
  33. 尽可能减少函数调用栈。如使用x= (x>0?x:-x)代替x= Mathf.Abs(x)
  34. Unity避免使用SetActive

开销问题:

    1. C#层到Native层的调用速度比C#层慢
    2. 会导致Canvas抛弃其VBO(顶点缓存对象)数据。重启Canvas会使Vanvas(包含所有的子Canvas)强制进行rebuild和rebatch进程。如果比较频繁,增加CPU的使用会造成帧率卡顿
    3. UI元素的网格定点数改变会造成堆内存分配,触发GC导致耗时(不过对UI元素进行位置移动不会造成堆内存分配)

优化:

    1. C#层设置标识,判断是否隐藏
    2. 将要频繁变化的UI元素与不频繁变动的UI元素分开(动静分离)
    3. 通过将UI元素的坐标移动到Canvas的范围之外的方法来显示与隐藏,避免SetActive的耗时以及SendWillRenderCanvases的耗时。
    4. 要更改单个UI的显隐可以通过GetComponent<CanvasRenderer>().SetAlpha(0);来实现,并且勾上CanvasRender.cullTransparentMesh使其不渲染网格,但是这样做还是会触发update等函数并且会触发点击事件
    5. 要更改父物体的显隐可以通过添加CanvasGroup组件设置透明度的方式来进行显示与隐藏。

UI优化:

  1. 制作图集
  2. 动静分离,子Canvas(但是会导致Canvas在子Canvas在子Canvas那边打断Batch,最好是不要使用多个Canvas)
  3. 相同图集和材质的放在一起,减少DrawCall
  4. 对Canvas下的所有CanvasRenderer深度优先遍历,生成一个队列如果在里面镶嵌Canvas,为空时不受影响,如果有任意元素会打断Batch
  5. 计算Depth: 每个Instrunction和前面的Instrunction判断是否相交,主要是判断相交同时 材质/贴图信息不一样的Instruction,如果有depth+1两个CanvasRenderer相交,同时材质/贴图不同,就要保序相交是指网格相交,不是RectTransform相交(Text是Overflow)
  6. Depth ->Material ID->Texture ID 渲染顺序(Depth表示这个元素能在第几步绘制)
  7. 不能设置图集的 要设置成2的幂次方
  8. 减少Mask的使用,如果需要可以优先考虑使用Rect Mask 2D(绘制完Mask所有节点之后 需要把Stencil复原,增加了一次DrawCall)
  9. 降低层级,减少深度遍历生成的消耗
  10. 非必要 关闭 MipMap Read/Write
  11. 纹理格式:推荐使用ASTC和ETC2 
    1. ETC2:对应的纹理分辨率为4的倍数,在对应的纹理开启MipMap时更具有严格的要求其分辨率为2的幂次方。否则,该纹理将被解析成未压缩格式
  12. 使用不同材质的实例化物体(instance)将会导致批处理失败。
  13. 在不移动不缩放的物体可以使用静态批处理,使用静态批处理不要再移动,不然开销的内存很大
  14. 禁止非图集贴图资源不合理的留白,会影响UGUI运行时自动和批
  15. 禁止使用修改Alpha值的方式来隐藏界面
  16. 尽可能降低图集留白,提高贴图利用率
  17. 尽可能将图集中大的图片改为地图加载
  18. 建议同一Canvas中使用到的图集数量控制在三个以内
  19. Canvas下的UI节点过多导致算法(贪心策略)耗时过长。主要消耗在Rebatch和Rebuild如果节点都是动态切不怎么变动,问题不大,Rebatch之后结果会进行缓存复用知道下一次节点变化;如果节点经常变动,会引起Canvas的Rebeach和Rebuild,CPU耗时就会响应增加。
  20. 在使用Layout时,不要去嵌套多的物体,这样在修改相关的一个Item时,所有的物体都会遍历,造成了大量的大量的计算浪费.
  21. 在使用完Layout排序之后禁用掉。

资源规范

音频

  1. 如果在音效不损失的情况下,可减少音频的Quality
  2. 如果不需要的双声道,可以关掉(开启Force To Mono)
  3. 较长的音乐,要设置成Streaming,不然整个资源会一次性加入内存中
    1. Decompress On Load:音频文件以压缩形式存放在磁盘中,解压后直接放在磁盘中,适合小音频。
    2. Streaming:音频放在磁盘中,加载时循环一下操作“从磁盘中读取一部分,解压到内存中,播放,卸载”存在占用较小,但是CPU消耗比较大
    3. Compressed In Memory: 音频文件已压缩形式放在内存中,加载时直接解压到内存中。CPU开销更大,加载速度和内存上更占优势,不适合大音频。

模型

  1. 重复的FBX的模型文件,可以把重复的网格丢弃。不然会重新加载到内存中
  2. 控制骨骼的数量和复杂程度
  3. Optimize Game Objects 勾选上:只有mesh,不会在出现骨骼,依然可以播放动画,如果是需要单独一个骨骼控制,可以在控制面版上 单独排除一个骨骼

Scene

  1. 搭建在Scene中的资源。不会被释放,除非切换场景。要尽可能把场景中的资源少放

Prefab

  1. 每一个Prefab不要过大,如果过大,尽可能去拆分,可以避免大内存的开销
  2. 同一个Prefab,尽可能使用一张图集,如果要使用多张图集/图片,控制在3个图集以内

小心插件

  1. 可能插件有多个版本的Json 造成的资源的浪费

AssetBundle

  1. 如果开发版本不会发生变化,可以去除掉TypeTree,这个是版本开发兼容性
  2. 大小尽量控制在1~2M,最大不要超过10M

IO

  1. 必须是异步的 不然会造成卡顿

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/3790.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小白入门C#编写MVC登录小案例

一、C#编写MVC登录小案例 &#x1f680;1. 新建MVC项目。 &#x1f680;2. 在Models文件夹下创建一个User类&#xff0c;包含登录所需要的用户名和密码属性。 namespace MvcLogin.Models {public class User{public string UserName{get; set;}public string Password{get;se…

遥感目标检测(1)--R3Det

目录 一、概述 二、三个挑战 三、网络架构​ 1、旋转RetinaNet 2、精细化旋转RetinaNet 3、与RoIAlign&#xff08;感兴趣区域插值&#xff09;进行比较 4、消融实验与对比实验 一、概述 R3Det论文中提到一个端到端的精细化的单级旋转检测器&#xff0c;通过从粗到细的逐…

Maven —— 项目管理工具

前言 在这篇文章中&#xff0c;荔枝会介绍如何在项目工程中借助Maven的力量来开发&#xff0c;主要涉及Maven的下载安装、环境变量的配置、IDEA中的Maven的路径配置和信息修改以及通过Maven来快速构建项目。希望能对需要配置的小伙伴们有帮助哈哈哈哈~~~ 文章目录 前言 一、初…

Unity根据目标点的位置计算Input输入

当给一个目标点&#xff0c;如果目标直接去目标点我们可以直接让position指向目标点的position。 如果是转换输入呢&#xff1f; 举例&#xff1a;例如一个人物动画里有两个参数X和Y&#xff0c;X&#xff08;- 1 &#xff0c;1) 表示向左走和向右走&#xff0c;Y (-1 , 1) 向…

leetcode 101.对称二叉树

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;对称二叉树 思路&#xff1a; 这道题和 leetcode 100.相同的树 类似&#xff0c;是上一道的变形题。✨leetcode 100.相同的树 代码链接&#xff1a;【往期文章】leetcode 100.相同的树。这道题把根的左子树和右子树看作两…

mysql统计千分位的字符串

mysql中统计sum(amount )&#xff0c;而amount是千分位的字符串&#xff0c;如何解决&#xff1f; 如果amount是千分位的字符串&#xff0c;需要将其转换为数值类型才能进行求和运算。在MySQL中&#xff0c;可以使用以下方法解决&#xff1a; 使用REPLACE函数去除千分位逗号&a…

回归预测 | MATLAB实现基于BiGRU-AdaBoost双向门控循环单元结合AdaBoost多输入单输出回归预测

回归预测 | MATLAB实现基于BiGRU-AdaBoost双向门控循环单元结合AdaBoost多输入单输出回归预测 目录 回归预测 | MATLAB实现基于BiGRU-AdaBoost双向门控循环单元结合AdaBoost多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.MATLAB实现基于B…

java8的常用的新特性

Java 8引入了许多新的特性&#xff0c;下面列举了一些常用的新特性&#xff1a; Lambda表达式&#xff1a;Lambda表达式是Java 8中引入的一种函数式编程特性&#xff0c;提供了一种更简洁和灵活的方式来编写匿名函数。 方法引用&#xff1a;方法引用允许直接引用已经存在的方…

Vue列表排序

开始前先回顾一下sort排序用法&#xff1a; 定义一串数组arr&#xff0c;使用sort排序&#xff0c;会收到前后两个数据项设置两个参数a&#xff0c;b。 注意&#xff1a;a-b 是升序 b-a 是降序 a-b升序&#xff1a; <script>let arr [12,11,2,5,76,33]arr.sort((a,b…

园区能源控制管理系统

园区能源控制管理系统是一种能够实现对园区内能源消耗、供应和分配进行实时监控、管理和控制的系统。该系统通过对园区内各种能源设备的数据采集、处理和分析&#xff0c;为管理者提供实时的能源使用情况和数据分析&#xff0c;从而帮助管理者制定科学的能源管理策略和节能措施…

unity 手动解析libunity.so 堆栈

参考&#xff1a;Android so库开发——addr2line查看so异常信息&#xff08;四&#xff09;_addr2line so_c小旭的博客-CSDN博客 CPU&#xff1a; ARM64(arm64-v8a) D:\Ndk\19.2.5345600\toolchains\aarch64-linux-android-4.9\prebuilt\windows-x86_64\bin\aarch64-linux-and…

TMS FlexCel for VCL FMX Crack

TMS FlexCel for VCL & FMX Crack 强大、广泛和灵活的组件套件&#xff0c;用于VCL和FireMonkey的本地Excel报告、文件生成和操作。 FlexCel for VCL/FireMonkey是一套允许操作Excel文件的Delphi组件。它包括一个广泛的API&#xff0c;允许本地读/写Excel文件。如果您需要在…

开源库nlohmann json使用备忘

nlohmann/json是一个用于解析JSON的开源C库&#xff0c;口碑一流&#xff0c;无需额外安装其他第三方库&#xff0c;还支持单个头文件模式&#xff0c;使用起来非常方便直观。 1. 编译 从官网https://github.com/nlohmann/json的Release页面下载单个json.hpp即可直接使用&…

华为云CodeArts Check IDE插件体验之旅

1 开发者的思考 近年来&#xff0c;ChatGPT的来临像一场突然出现的风暴&#xff0c;程序员是否马上被取代的担忧出现在媒体上了&#xff0c;作为软件开发小白&#xff0c;前不久我也陷入了这样的深思之中&#xff0c;但认真的想了下&#xff0c;ChatGPT就如自动驾驶一样&#…

MySQL 判断 JSON 数组是否相等

文章目录 1.问题2.使用 JSON_CONTAINS 与 JSON_LENGTH参考文献 1.问题 JSON&#xff08;JavaScript Object Notation&#xff09;是流行的互联网应用服务之间的数据交换格式。 MySQL 从 5.7 版本开始支持 RFC 7159 定义的 JSON 规范&#xff0c;主要有 JSON 对象 和 JSON 数组…

NAS 问题处理记录

在解决自动配网的过程中&#xff0c;突然NAS不给力&#xff0c;偏偏这个时间找事情。上面这两个问题&#xff0c;说不复杂也不复杂&#xff0c;主要是自己在完全远程处理&#xff0c;很多不方便。当然少不了师弟的助攻&#xff0c;很感谢我的师弟帮忙&#xff0c;实验室的网络不…

ubuntu20.04系统安装使用labelme标注数据集

一、Anaconda的安装 请参考&#xff1a;MediapipeVSCodeAnaconda 实时检测手部关键点并保存视频_苦瓜汤补钙的博客-CSDN博客 二、Labelme的安装 1.打开终端创建虚拟环境 # 创建labelme的环境 conda create -n labelme python3.9 输入“y”&#xff0c;然后回车。 2.激活虚拟…

基于单片机的智能路灯控制系统人体感应灯光控制系统的设计与实现

功能介绍 以51单片机作为主控系统&#xff1b;LCD1602液晶显示当前时间、年月日、时分秒&#xff1b;按键看看有设置自动手动模式&#xff1b;3路红外探头用来感应当前3个区域是否有人&#xff1b;按键可以设置当前时间、开启和关闭教室灯光时间&#xff1b;在手动模式下&#…

uni-app解决A页面调用方法后,自动触发B页面的方法

项目场景&#xff1a; tabbarA页面,触发一个点击事件,需要tabbarB页面自动触发请求接口的方法 问题描述 tabbar A页面触发一个点击事件后, tabbarB页面在onload钩子函数中去请求接口,只有tabbarB页面首次打开时会触发onload钩子函数请求接口,再次跳转tabbarB页面不触发onload…

【JavaEE面试题(九)线程安全问题的原因和解决方案】

多线程-初阶 4. 多线程带来的的风险-线程安全 (重点)4.1 观察线程不安全原因是 1.load 2. add 3. save 4.2 线程安全的概念4.3 线程不安全的原因最根本的是 操作系统对线程的调度是随机的★1. 修改共享数据&#xff08;多个线程修改同一个变量&#xff09;★2. 操作不是原子性★…