| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 游戏开发 -> Unity 性能优化-代码 -> 正文阅读 |
|
[游戏开发]Unity 性能优化-代码 |
1、GameObject本机-托管桥接与C#对象相比,GameObject和MonoBehaviour是特殊对象,因为它们在内存中有两个表示:一个表示存在于管理C#代码相同系统管理的内存中,C#代码是用户编写的(托管代码),另一个表示存在于另一个单独处理的内存空间中(本机代码)。数据可以再这两个内存之间移动,因此每次移动都会导致额外的CPU开销和 可能的额外内存分配,这种效果一般称为跨越本机-托管的桥接。 由以上理论,触发这种额外开销的有以下两种常见情况:
2、获取组件优化Unity中获取组件GetComponent()有3个可用的重载,分别是GetComponent(string),GetComponent< T >()和GetComponent(typeof(T))。在这三个方法中,最好使用GetCompnent< T >()重载。 此外,GetComponent()方法也不应该运用在类似Update()逐帧计算中,最好的方法是初始化过程中(Awake或Start等)就获取引用并缓存它们,直到需要使用它们为止。同样的技巧也适用于在运行时决定计算的任何数据,不需要要求CPU在每次执行Update()时都重新计算相同的值,因此可以提前将其缓存到内存中。 3、移除空的回调定义在MonoBehaviour脚本中常用其周期函数,常用的有Awake()、Start()、Update()、FixedUpdate()等,这些回调函数会在场景第一次实例化时添加到一个函数指针列表中,又因为在所有的Update()回调(包括场景中所有的MonoBehaviour)完成之前,渲染管线不允许呈现新帧,因此当场景中有大量MonoBehaviour脚本时(包含空的Start()或Update()),场景的初始化以及每帧都会严重消耗资源从而影响帧率。因此我们需要在编写脚本时注意删除空的周期函数,例如Start(),Update()等。 4、运行时修改Transform的父节点Transform组件的父-子关系比较像动态数组,因此Unity尝试将所有共享相同父元素的Transform按顺序存储在预先分配的内存缓冲区中,并在Hierarchy窗口中根据父元素下面的深度进行排序。这种数据结构允许整个组中进行更快的迭代,对于物理和动画等多个子系统有利,但是如果将一个GameObject的父对象重新指定为另一个对象,父对象必须将子对象放入预先分配的缓冲区中,并根据新的深度对所有Transform进行排序。另外如果父对象没有预先分配足够的空间,就必须扩展缓冲区。对于较深、复杂的GameObject结构,这需要一些时间来完成。 通过GameObject.Instantiate()实例化新的GameObject时,想为其设置一个父物体,在我们使用时很多情况会写成类似以下代码:
以上情况在listItem实例化之后立即将Transform的父元素重新修改为另一个元素,它将丢弃一开始分配的缓冲区,为了避免这种情况,应该将父Transform参数提供给
5、减少对Transform的改变不断更改Transform组件属性,也同时会向其他组件(如Collider、Rigidbody、Light、Camera等)发送内部通知,这些组件也必须进行处理,因为物理和渲染系统都需要知道Transform的新值,并相应进行更新。 在复杂的过程中,在同一帧中多次替换Transform组件的属性很常见,每次Transform发生改变时,都会触发内部消息。因此,应该尽量减少修改Transform属性的次数,方法是将其变化缓存在一个成员变量中,只在帧的末尾修改Transform值,如下所示 6、避免在运行时使用Find()和SendMessage()
7、Vector计算在进行向量乘法计算时,有一点需要注意乘法顺序,因为向量乘比较耗时,所以我们应该尽可能减少向量乘法运算。可以基于之前CustomTestTimer来做一个实验:
最终结果如下: 由结果可以看出,以上两个方法结算结果相同,但是Func2却比Func1耗时少,因为后者比前者少了一次向量乘法。所以,应该尽可能合并数字乘法,最后再进行向量乘。 8、循环在迫不得已需要写多重循环时,应该尽量把遍历次数较多的循环放在内层。做测试如下:
测试结果如下: ?9、MonoBehaviour非必要不要继承MonoBehaviour,因为MonoBehaviour中有很多unity定义的属性方法。实例化出来用不到,就是浪费。 10、拆装箱减少拆装箱操作,相同操作方法用泛型 一种常规易造成拆装箱的写法:
上面会造成拆装箱,下面的写法就没问题
注意:string str = string.Format("{0}", i.ToString());依然会有拆装箱 11、string 与 stringBuilder多次操作字符串使用stringBuilder,对string每次操作都会生成新的对象,从而产生GC垃圾。 stringBuilder如果能确定长度,最好先指定长度。 12、结构体对于值类型的集合结构使用结构体。占的是栈内存,栈内存效率较高 13、系统自带默认值Vector3 v3 = new Vector3(0,0,0); 与 Vector3 v3 = Vector3.zero;使用Vector3.zero更好,因为减少了一次new的过程。Vector3.zero全局只有一个。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/27 23:42:47- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |