使用ScriptableObject序列化Unity Object

Posted on 周三 29 十一月 2017 in Unity

在Unity中,Unity Object的序列化必须依赖GameObject。像这样是不行的:

[Serializable]
class ObjectSheetData : SheetData
{
    public Object data = null;
}

ObjectSheetData objData = new ObjectSheetData();
objData.data = 某个Sprite;

//序列化到data.byte
BinaryFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("data.byte", FileMode.Create, FileAccess.Write, FileShare.None);

formatter.Serialize(stream, objData);
stream.Close();

Unity会提示

SerializationException: Type UnityEngine.Sprite is not marked as Serializable.

通常的做法是将要序列化的数据附加到一个GameObject上,然后将GameObject做成Prefab,在要使用数据的地方引用Prefab就可以了。这里提供一个算是比较通用的脚本,用来实现类似表的功能。 但我们发现这是一种数据附加到界面上来存储的方式,有违界面与数据分离的设计方式。

ScriptableObject提供了一种不依赖GameObject的序列化数据的方式。

我们可以将数据封装成这样:

public class ScriptableData : ScriptableObject
{
    public string myName = "";
    public int myLevel = 0;
    public Sprite myIcon = null;
}

提供一个创建数据文件的接口:

[MenuItem("ScriptableTest/CreateData")]
public static void CallFunc()
{
    ScriptableData data = ScriptableObject.CreateInstance<ScriptableData>();
    data.myName = "";
    data.myLevel = 0;
    data.myIcon = null;

    //ScriptableDataPaht是数据文件的路径
    AssetDatabase.CreateAsset(data, GlobalValue.ScriptableDataPaht);
    AssetDatabase.SaveAssets();
}

创建出来的文件是这样子的:

Alt text

填上数据后,就可以在运行时读取了:

ScriptableData _data = AssetDatabase.LoadAssetAtPath<ScriptableData>(GlobalValue.ScriptableDataPaht);
nameInput.text = _data.myName;
levelInput.text = _data.myLevel.ToString();
image.sprite = _data.myIcon;