1.Obtain Components using the fastest method
Unity有多种Getcomponet的方法:
GetComponent(string),
GetComponent<T>()
GetComponent(typeof(T))
哪种效率最高会跟随Unity版本的变化而变化,对于Unity 2017,本书作者的测试是GetComponent<T>()方法最给力,和GetComponent(typeof(T))差不太多。至于GetComponent(string),可定是最差了,跟其他俩个方法有很大的差距,很容易理解,毕竟是用的是神坑的string作为参数啊
2.Remove empty callback definitions
Awake(), Start(), Update()等Unity自带的方法在没使用时删除掉。因为即使是空方法,Unity也需要在生命周期的对应时间点去调用函数,依然会有开销。关于Unity的生命周期,可以查看对应介绍https://docs.unity3d.com/Manual/ExecutionOrder.html
特别需要注意的是Start 和 Update方法。因为当创建一个脚本时,Unity为它默认的添加了这俩个方法。
例如Start()方法,虽然是在Instantiate时只调用一次,但是当同时有大量脚本需要调用各自的start方法时,就有可能会带来Scene初始化变慢,浪费CPU导致帧率下降和卡顿。
举个栗子,两个物体碰撞时,我们可能会搞个特效出来,再显示个伤害数字文本,再播个小音效等等,这一瞬间会对CPU做出很多变化,这一帧一下子要干一堆事。但是只有这一帧整个生命周期包括Start,Update该做的都做完了才能进行下一帧,此时就可能导致帧率下降。
作者做了个测试,30000个脚本,两组对照组,一组没有空的函数,一组有空的Start 和 Update,结果显而易见。
特别需要警惕的是一个GameObject可能会有多个component,如果componet都有没必要的空函数,后果很残忍。
要解决这个很简单,删掉空函数就ok了,各家IDE工具也都支持正则,下边这个正则就可以找到所有的空Update函数。对于OnGUI() OnEnable()等等其他函数都是同样道理。
Update要谨慎使用,Update函数常见的使用不当的情形:(水平有限,这段有点怎么翻译都难翻译出原味儿,直接看英文吧还是)
1.重复计算并不常用或根本没用过的value
2.承担了过多本可以共享结果的工作
3.对于一些工作其实没必要这么高的调用频率
3. Cache Component references
在Unity编程中,重复计算是一个常见的问题,特别是对于GetComponent()这种函数消耗更大(原理在之后的第八章会讲,是因为Native内存)
比如下边这个例子,每次计算Damage,都要重复获取rigidbody等5个脚本的引用,这对CPU很不友好,如果要是这函数是在Update函数里每帧都调用,那简直是灾难。
我们可以用一丢丢内存(32 or 64bits)来换取这部分性能,为将来的使用缓存这些引用。除非有极其严格的内存瓶颈,毫无疑问这种方式更nice,将会节省很多CPU资源。同样的道理对于计算Value也同样适用,计算一次缓存下来避免多次计算,都可以提高效率。