为什么C#使用[System.Serializable]来保存实例? (Unity3D)

时间:2013-07-27 15:08:06

标签: c# serialization unity3d

我想制作一个程序,如果从检查器获取TextAsset(它放在'ExampleEditor'中),它会创建一个自定义数据实例以使用混合形状动画。

首先,我使用[System.Serializable]创建自定义数据类。

public class Matrix {
    public int row;
    public int col;
    public double[,] mat;
}

我的策略是使用TextAsset,从TextAsset解析字符串,最后将Matrix实例转换为'Example.cs'中的字段变量。我想当它初始化并首先分配时,我能够在Example实例中使用该变量。但是,它没有用,它抛出'NullReferenceException'。

所以我找到了使用'[System.Serializable]'的解决方案。它确实有效。 (我知道Unity3D不为它们的序列化方法提供多维数组。)

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

[System.Serializable]
public class Matrix {
    [System.Serializable]
    public class mRow {
        public List<float> aRow = new List<float>();
    }

    [HideInInspector]
    [SerializeField]
    public int row;

    [HideInInspector]
    [SerializeField]
    public int col;

    //[HideInInspector]
    [SerializeField]
    public List<mRow> mat = new List<mRow>();
}

最后,我知道解决方案,但我不知道为什么会出现这个问题。它与GC有关吗?

1 个答案:

答案 0 :(得分:8)

你的问题不是很清楚,但我想知道你不理解的是什么。

  

我的策略是使用TextAsset,从TextAsset解析字符串   最后将Matrix实例创建为'Example.cs'中的字段变量。

您没有解释您是如何做到的(也许从自定义检查器调用解析函数?)。 但是,尽管如何设置从编辑器初始化字段,如果字段不可序列化,则从编辑器切换到播放模式时它将为null

这是因为当进入播放模式时,Unity3D序列化了填充引擎的相对C#类的所有C++类。如果某个字段不是Unity可以序列化的类型的公共字段(甚至是标有SerializeFieldAttribute的私有字段,则始终是Unity可以序列化的类型),Unity3D不会序列化它。

因此,当您切换到播放模式时,引用将为空。

换句话说,您想要从编辑器初始化的所有字段必须是可序列化的,以便在播放模式下使用。

[SerializeField]
public List<mRow> mat = new List<mRow>();

上面的代码没有多大意义。如果您计划从检查器初始化可序列化字段,请不要按代码初始化它,否则您最终可能会丢失引用。 这种错误的一个例子:

[SerializeField]
private List<int> aList;

public void Start()
{
  aList = new List<int>();
} 

上面的代码会引起麻烦。如果您已从检查员初始化aList,则会将其正确序列化,但当您切换到播放模式时,会调用Start回调,aList将重新初始化,您最终将会对空列表的引用。

这是一个很好的blog post,解释了Unity3D如何处理对象序列化的详细信息。读吧!