| |
|
开发:
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性能优化之关于脚本的优化与注意事项 |
写在前面:本文所述脚本优化就是多使用那种方式,尽量不要使用那种方式,那种方式会浪费资源,以及为什么会浪费资源,某些高效率的框架以及系统是怎样制作的 使用最快的方式获得组件通常情况下,我们获取组件的方式中,最常用的方法之一就是GetComponent,但是GetComponent有几种变体,这几种变体的执行效率是不一样的,分别有GetComponent、GetComponent(string)、GetComponent(typeof(T)) ,这几种变体是有效率区别的,通过简单测试(网上也有很多测试结果)显示,GetComponent(T)<> > GetComponent(typeof(T)) >> GetComponent(string) ,前两者相比,差距并不是很明显,但是第三个的效率要明显低于前两者, 第三个变体一般应用于调试于诊断这种对于性能要求不是很高的场景, 移除空的回调定义在通过unity创建脚本的时候,一般都会自动的创建上start、update等回调函数,开发人员有的时候可能会用到,但是更多的时候是用不到的,那么这种空的回调定义就会在一定程度对性能产生影响,为什么呢? 缓存组件引用当我们经常使用的GetComponent,很大的一个避讳就是,什么时候用,什么时候获取,用一次,获取一次,这样都是很不好的行为,实际上,对于将要使用的的组件,我们更好的方法是在初始化的时候获取并保存组件,然后再使用的时候拿来用就可以了,这样做的优点就是,消耗少量的内存,但是每次都会减少一些CPU开销; Update、Coroutines、InvokeRepeating这样的代码是不是很常见?
实际上想来看看,对于这个text函数,我真正想要调用的频率有每一帧都调用的这种需求吗?这种情况起始就是以超过了需要的频率重复调用某段代码,现在来修改一下
这样的话,减少了调用的频率,也减少了CPu的负担
协程的概念都清楚,既然我们想要控制一下text的调用频率,使其不至于增加不必要的负担,那么适用协程就好了,如果使用协程,还有几点需要注意
减少text调用频率的第三种方法:使用InvokeRepeat,实现方案很简单
但是它和协程的一个重要区别就是,InvokeReapting完全独立于MonoBehaviour和Gameobject的状态,如果想要停止调用InvokeReapting,第一种方法就是调用cancelInvoke,第二种就是销毁相关联的MonoBehaviour或者其父gameobject(禁用不会停止) 避免从GameObject种取出字符串属性通常情况下,从对象种检索字符串属性与检索C#中的任何引用类型属性是相同的,不应该增加内存成本,但是从GameObeject中检索字符串属性是一种意外的本机-托管桥接的方式,(一方面会随着正常代码保存在堆栈中与管理C#代码放在同一个系统中进行管理,一方面又会随着C#代码-LL-机器语言),受次影响的两个属性是tag、name,但是tag有避免本机-托管桥接的方法,CompareTag()这个方法完全的避免了本机-托管桥接 使用合适的数据结构不同的数据结构对于不同的场景有不同的效率,比如,如果仅仅是需要遍历一组对象,最好使用列表,如果需要快速找出那个对象映射到另一个对象,并且还能遍历数据,最好使用字典等等 避免运行时修改Transform的父节点在unity的早期版本(5.3甚至更早)Transform组建的引用通常在内存中是随机排列的,这意味着在多个transfor上迭代时很慢的,但是这样做的好处就是,修改一个gamobject的父节点为另一个对象并不会产生显著的性能下降; 但是在5.4以后,unity尝试将所有共享相同父元素的transform按照顺序存储在预先分配的内存缓冲区的内存中,并且在Hierarchy窗口中按照父元素下面的深度进行排序,这样的话,进行迭代时,速度更快,对于物理和动画等子系统特别有利,但是如果要在运行时将某个gameobject的父对象重新指定为另一个对象的话,父对象必须将新的子对象放入预先非陪的内存缓冲区中,并且根据深度重新对这血transform进排序,如果最开始的缓冲区不够大,还需要进行扩容,这样极大的增加了CPU的开销; 怎样避免呢? 在使用Instantiate()实例化新的gameobject的时候,有一个参数是设置实例化物体的父节点,默认值是null也就是放在Hierarchy窗口的根元素下,在Hierarchy窗口根元素下的所有transform都需要分破欸一个缓冲区来储存它当前的子元素以及以后可能添加的子元素,如果在实例化之后重新修改为另一个元素,那么他就会丢弃刚刚分配的缓冲区,为了避免这种情况,还是需要将这个parent参数提供给instantiate; 注意和缓存transform的变化如果某transform发生了变化,不要着急去提交,或者直接去改变,例如position、rotation、scale等,因为这些属性会导致大量的未预料到的据称的乘法计算,为什么呢?因为这些值发生改变之后,会通过其父对象生成正确的transform表示,当所修改的对象在场景中的位置越深,这种计算量就越大,因此尽量修改locationposition、locationRoadtation、localScale 避免在运行时使用Find、SendMessage众所周知,sendMessage、和find的方法很昂贵,要不惜一切代价去避免使用,下面给出几种可以避免使用这两个函数的用例
禁用未使用的脚本和对象场景有的时候很繁忙,特别是在构建大型、开放的时节时,在update回调中,调用代码的对象越多,他的伸缩性就越差,游戏就越慢,然而如果许多正在处理的内容在玩家视野之外,实际上可以不用去处理它,直接禁用就好 通过可见性禁用对象可以通过一种叫做视锥剔除的技术,来避免渲染对玩家相机试图不可见的对象,避免渲染隐藏在其他对象后面的对象,但是这些时渲染层面的优化,它不会影响在cpu上执行任务的组件,比如AI脚本,用户界面和游戏逻辑,所以需要我们自己控制这种行为,可以使用Became Visible和O你Became Invisible这两种方法来实现,
通过距离禁用对象正常情况下,在游戏中如果某个NPC距离我们的角色距离很远,实际上是不需要这个NPC做什么操作的,那么为了节省资源,可以规定NPC,如果监测到本身与角色的距离超过多远,就禁用自身,代码如下
使用距离的平方而不是距离可以非常肯定的说,CPU更加擅长于计算浮点数的乘法,而不擅长于计算平方根,因此,如果可能的话,把使用的Distance()、magnitude所计算的两个vector距离转换为sqrMagnitude会减少大量的CPu开销,这样做的缺点是,精度可能不是那么准,因此,如果在精度允许不是那么准的前提下,可以这样修改。 最小化反序列行为Unity中的序列化系统主要应用于场景、预制体、ScriptableObjects和各种资产类型,当对象被保存到磁盘的时候,会使用YAML格式将其转化为文本文件,然后可以再将其反序列化成原始对象类型,所有的GameObject以及其属性,都会在序列化预制体或者场景的时候进行序列化,包括其私有和受保护的字段,子物体等 这些序列化的数据会绑定在一个大的二进制数据文件中,也就是Unity内部的序列化文件,相对而言,从磁盘读取和反序列化数据是一个比较慢的过程,因此,所有的反序列化活动往往都伴随着比较大的性能成本。 这种反序列化一般发生在Resources.load的时候,由于需要加载的数据很多,并且每隔预制体的子组件都是序列化过的,因此层次结构越深,需要反序列化的数据就越多(带有很多空对象或者说每隔对象至少都包含一个Transform组件),虽然说如果某个数据已经加载过,第二次加载的时候会快很多,但是像这样加载一个打行的序列化数据集可能会在第一次加载的时候造成CPU显著峰值,如果在场景开始的时候立即需要他们,可能会延长加载时间,如果在运行的时候加载,可能会造成掉帧
叠加、异步地加载场景加载场景的方式有以下几种
同样的也可以卸载场景,从内存中清除出来,这样可以节省一些内存或者提升一些运行时性能,同样也可以通过异步的方式进行清除 自定义Update层当Unity调用Update的时候,实际上时调用他的任何回调,都要经过前面所说的本机-托管的桥接,这是一个比较昂贵的任务,实际上,调用一千个Update所消耗的资源要比包含一千个常会函数的一个Update所花费的成本高很多,所以自定义Update是一个比较好的方式,代码如下 单例层
管理层
接口层
实现层
使用层
记录自己这段时间所学,借鉴书籍 unity性能优化(第二版) |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
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 20:25:23- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |