记录一个Unity序列化的垃圾回收问题

在优化代码的时候,发现这样一段写法

public class Test : MonoBehaviour
{
    public List List = new List();

    private void Awake()
    {
        
    }

    void Start()
    {
        foreach (var num in List)
        {
            //Do Something;
        }
    }
}

由于List是可以序列化的,于是在界面上就会如下所示:

好了,问题了来了,在运行时,我们自己New的List和外部传进来的List,是同一个List吗?如果没有,是否意味着我们浪费了一次GC.Alloc? 

为了方面测试,我们新写一个类,名字叫做XList,我们重写类的构造函数,让类在构造函数中打印自己的HashCode

public class XList : List
{
    public XList() : base()
    {
        Debug.LogError("New XList : " + GetHashCode());
    }
}

然后修改测试代码:

public class Test : MonoBehaviour
{
    public List List = new XList();

    private void Awake()
    {
        Debug.LogError("Awake" + List.GetHashCode());
    }

    // Start is called before the first frame update
    void Start()
    {
        Debug.LogError("Start" + List.GetHashCode());
    }
}

运行代码:

记录一个Unity序列化的垃圾回收问题_第1张图片

我们可以发现,确实Unity总共New了两次List对象,并且都是在Awake之前。通过对比HashCode可知,第一次是我们默认New的空对象,第二次是UnityNew出来的并完成了反序列化。

因此我们就浪费了一次GC.Alloc

那如果我们自己不new对象,在面板上也放着不管,那这个List是null还是一个为0的对象呢?是为0的对象。所以安全性也不存在问题。

 最终修改代码:

public class Test : MonoBehaviour
{
    public List List;

    private void Awake()
    {
        Debug.LogError("Awake" + List.GetHashCode());
    }

    // Start is called before the first frame update
    void Start()
    {
        Debug.LogError("Start" + List.GetHashCode());
    }
}

运行:

由于此时List失去了实际的XList类型,因此XList的构造函数不再被调用。不过我们还是可以推测出,我们确实节省了一次GC分配

你可能感兴趣的:(C#,优化,UNITY,unity,游戏引擎,c#,性能优化)