技术学习03_Unity优化

Unity3d中的细节优化 第二篇

2019-08-15  本文已影响0人  _ArayA_

1.MonoBehaviour的细节优化

在MonoBehaviour中,如果没有相应的事件要处理,请删除默认的空函数

Update、FixedUpdate、LateUpdate中,如果没必要每帧的逻辑,可以降低频率,例如:

Void Update(){

    if(Time.frameCount%6==0){

        DoSomething();

    }

}

如果间隔更长,没必要每帧的逻辑,使用周期性的协程更妥当,例如:

InvokeRepeating("DoSomeThing",0.5f,1.0f);

Gameobject不可见时,设置 enabled = false 时,update 就会停止调用。

在update 中尽量不要调用查找对象或组件方法如 FindByTag 或Find 等等,可以在start中获得引用,然后使用。

2.协程会产生GC

使用 yield return new WaitForSeconds() 将会每帧导致 21Byte GC,而yield return null 会产生 9 Byte GC。

所以因为GC问题,所以不推荐使用协程,Invoke或 StartCoroutine。


3.Transform细节优化

Transform在初始化时,使用内建的数据,如 Vector3.zero 而不是 new Vector(0, 0, 0),

transform.localRotation = Quaternion.Euler(Vector3.zero);

transform.localScale =Vector3.one;

transform.localPosition =Vector3.one;

4.GameObject 细节优化

缓存Gameobject,在脚本挂载对象引用,可减少查找。

缓存组件,调用 GetComponent 函数有查找开销,用变量挂载到脚本使用,降低开销(GetComponent时如果获取到空的组件也会产生GC)。

查找对象标签用if (go.CompareTag (“xxx”)来代替if (go.tag == “xxx”)。GameObject.tag会在内部循环调用对象分配的标签属性,并分配额外的内存,并且效率也更低。

SendMessage,BroadcastMessage,SendMessageUpwards,少用这三个函数,因为它们的实现是一种伪监听者模式,利用的是反射机制,性能非常低。具体的性能大概是委托的十分之一,建议使用委托代替。

5.优化数学运算

尽量采用整型代替浮点型,除法改乘法。例如:

float a = 2.0 如果精度允许改为 int a = 2

a/2,改为a*0.5

巧用位操作,代替2的倍数的,整乘整除。例如:

int a = 100 >> 1  相当于除2取整 结果为 50

int a = 100 >> 2  相当于除4取整 结果为 25

int a = 100 << 1  相当于乘2取整 结果为 200

int a = 100 << 2  相当于乘4取整 结果为 400

在运算操作时,能整不浮,能乘不除。而位操作是操作符比传统乘除效率要高,适合大量计算时使用。

同时位操作符,还可用来取整操作,更多技巧以后独立开篇具体说明

6.遍历数组的技巧

在遍历数组时,我们会用到Length属性。很多人不知道的是这个属性其实是会动态计算数组的长度的。

举个栗子:

int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};

            int a;

            const int count = 10000000;

            Stopwatch sw = new Stopwatch();

            sw.Start();

            for (int j = 0; j < count; j++)

            {

                for (int i = 0; i < arr.Length; i++)

                    a = arr[i];

            }

            sw.Stop();

            Debug.Log("time1:" + sw.ElapsedMilliseconds);

            sw.Reset();

            int len = arr.Length;

            for (int j = 0; j < count; j++)

            {

                for (int i = 0; i < len; i++)

                    a = arr[i];

            }

            sw.Stop();

            Debug.Log("time2:" + sw.ElapsedMilliseconds);

time2是将arr.Length缓存到len里的耗时。下面是具体的耗时图:

可以得知,当循环数量很大时,数组获取Length的开销还是挺大的,并且数组越大耗时也越大。希望大家不要忽视这个细节。

上一篇下一篇

猜你喜欢

热点阅读