加载 MonoBehaviour 类时, public属性因为序列化所产生的性能开销问题

我们都知道 MonoBehaviour 类的 public 属性是会被unity自动序列化的,然后你就可以直接在对象上设置参数了,像这样:
这里写图片描述
但是这样的开销其实挺大的。


我们现在创建2种类,一种是集成MonoBehaviour的,绑定在cube上,我们来加载1000个进来。一种是普通的c#类,我们也加载1000个进来。(为什么加这么多,是因为加少了怕看不出区别来)
测试环境为Unity 4.6.6f2,我的 5.3.1 出了点问题,所以只能拿个版本稍低点的来演示了


加载类:

public class GameMain : MonoBehaviour
{
    public GameObject cube1;
    public GameObject cube2;

    public bool open1;
    public bool open2;

    private List<Cube1> m_cubeList1;
    private List<Cube2> m_cubeList2;

    // Use this for initialization
    void Start()
    {
        System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
        stopwatch.Start();

        if (open1 && cube1 != null)
        {
            m_cubeList1 = new List<Cube1>();

            for (int i = 0; i < 10000; ++i)
            {
                GameObject go = (GameObject)GameObject.Instantiate(cube1);
                go.transform.parent = transform;

                Cube1 temp = go.GetComponent<Cube1>();
                m_cubeList1.Add(temp);
            }
        }

        if (open2 && cube2 != null)
        {
            m_cubeList2 = new List<Cube2>();

            for (int i = 0; i < 10000; ++i)
            {
                GameObject go = (GameObject)GameObject.Instantiate(cube2);
                go.transform.parent = transform;

                Cube2 temp = new Cube2(go);
                m_cubeList2.Add(temp);
            }
        }

        stopwatch.Stop();
        System.TimeSpan timeSpan = stopwatch.Elapsed;

        Debug.Log("加载用时 = " + timeSpan.TotalSeconds);
    }
}

Cube1:

public class Cube1 : MonoBehaviour
{
    public string txt_1 = "";
    public string txt_2 = "";
    public string txt_3 = "";
    public string txt_4 = "";
    public string txt_5 = "";
    public string txt_6 = "";
    public string txt_7 = "";
    public string txt_8 = "";
    public string txt_9 = "";
    public string txt_10 = "";

    void Start()
    {

    }
}

Cube2:

public class Cube2
{
    public GameObject gameObject;
    public Transform transform;

    public string txt_1 = "";
    public string txt_2 = "";
    public string txt_3 = "";
    public string txt_4 = "";
    public string txt_5 = "";
    public string txt_6 = "";
    public string txt_7 = "";
    public string txt_8 = "";
    public string txt_9 = "";
    public string txt_10 = "";

    public Cube2(GameObject go)
    {
        gameObject = go;
        transform = gameObject.transform;
    }
}

我们看到它们都有 public 的属性,然后我们看它们分别运行的情况。

cube1
这里写图片描述

cube2
这里写图片描述

这里我们看到了,一个用时519.01,一个用时314.20,差的还是蛮大的,而且 gc 时的内存也是超大的。MonoBehaviour 中的 public 属性导致了 2.8mb 的 gc,是普通c#类的2倍还多。


然后我们再把cube1和cube2中的public属性都去掉再来看看运行结果

cube1
这里写图片描述

cube2
这里写图片描述

这里我们看到,改善最明显的就是 gc 了,直接从 2.8mb 掉到了 0.7mb,2者之间的时间差距也有所缩短。


由此我们得出结论,MonoBehaviour 对 public 属性进行的序列化操作,其实是挺费的,且会产生大量的 gc,在这一点上,就不如使用普通的 c# 类来对 GameObject 进行管理来的高效了,但是我们也不能忽视 MonoBehaviour 和它的 public 属性所带来的便利性。

所以如果你需要使用 MonoBehaviour 特性的话,我建议你把 public 的属性改写成 get,set 的形式,然后用编辑器的 Editor 类在 GameObject 上添加可以赋值的控件,通过控件将值传递到 get,set 上,这样我们既达到了可以在 GameObject 上设置参数的目的,还避免了 MonoBehaviour 对 public 属性进行序列化所产生的性能开销。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值