C#代码优化:拯救你的CPU耗时
Posted 侑虎科技
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#代码优化:拯救你的CPU耗时相关的知识,希望对你有一定的参考价值。
之前,我们已经对中和资源/Prefab的内容做了总结(详情可扫描文末长图),后续UWA也会和大家一起努力,进一步丰富这些检测内容。今天我们要聚焦的是本地资源检测中的C#代码相关的检测项。
1、类中存在OnGUI方法
规则里涉及到的OnGUI,它是Unity的IMGUI系统绘制UI所调用的方法。该方法如果写在继承了Monobehavior的脚本上,那么Unity会在每一帧自动对其进行调用。
我们在上面的规则中简单说到了“Monobehavior”,Unity中的脚本其实默认都是继承自这个Monobehavior。Update、LateUpdate和FixedUpdate属于Monobehaviour类的“Messages”,虽然不由Monobehavior类继承而来,但是在Monobehaviour类的脚本中会生效——如果脚本中写上了这些方法,相应的脚本放到场景中,并且enable为true,那么游戏运行过程中每帧都会对其进行调用。
-
这些方法是Native层对托管层的调用,C++与C#之间的通信本身存在一定的开销。 -
当调用这些方法时,Unity会进行一系列安全检测(比如确保GameObject没有被销毁等)导致CPU时间的消耗。
4、该类的方法中存在ComputeBuffer.GetData调用
5、该类的方法中存在对纹理SetPixels的调用
6、该类的方法中存在GameObject.SendMessage调用
7、该类的方法中存在GetComponentsInChildren调用
该类的方法中存在GetComponentsInParent调用
GetComponentsInChildren用于获得当前GameObject及其子节点的所有给定类型的组件,返回的是一个包含所有符合条件的对象的数组;而GetComponentsInParent则是用于获得当前对象及其父节点上的所有给定类型的组件。当然这里我们在说法上忽略了对组件隐藏情况的讨论。
8、该类的方法中存在FindObjectsOfType调用
9、该类的方法中存在Reflection相关函数的调用
反射(Reflection)是一项用来在代码运行时做绑定的技术。如果代码需要获取的类型、调用的函数等信息是在运行时才能被明确的,那么就需要用到反射。
10、该类的方法中存在对 Renderer 进行 material/materials 的获取
在Unity中,如果对Renderer类型调用.material和.materials,那么Unity就会生成新的材质球实例。其主要影响如下:
通过.material,创建材质实例,并修改属性的方式实现多样的渲染效果,时间开销会较高。这里可以参见。
使用相同Shader,但因为Material实例不同的GameObject,所以无法进行合批,导致DrawCall增加,变相造成了CPU耗时的增加。
每次对新的GameObject的Renderer调用.material,都会生成一个新的Material实例,且GameObject销毁后,Material实例无法自动销毁,这会对资源管理造成一定的成本,想要处理的话就需要手动调用“OnloadUnusedAssets”来卸载,但这样就造成了性能开销;管理不好可能会造成材质球大量冗余甚至泄露,极端情况下甚至会导致过高的内存。
建议通过主动MaterialPropertyBlock的方式修改材质属性,或者人为对有限个材质实例进行管理,效果相同的物体通过sharedMaterial来共用材质实例。
以上是关于C#代码优化:拯救你的CPU耗时的主要内容,如果未能解决你的问题,请参考以下文章
思考:网络性能优化:网络 -- cpu -- 线程数 -- 单个任务耗时 --- qps --- 并发