Unity與C#的序列化與反序列化【轉載】

 

序列化操作在我們的開發中使用的十分普遍,本文記錄了公司最近分享會上關於這部分的講解,希望能幫助大家對序列化有更系統的瞭解。

概念

序列化又稱串行化,是.NET運行時環境用來支持用戶定義類型的流化的機制。其目的是以某種存儲形式使自定義對象持久化,或者將這種對象從一個地方傳輸到另一個地方。

簡單來說就是將對象保存到文件中。如Unity的場景文件和預製體默認就是以二進制的文件保存在工程目錄下。

Unity序列化

在Unity中,在檢視面板中可以看到的,就是被成功序列化了的參數。與序列化相關的常用的關鍵字有SerializeField,HideInInspector,NonSerialized,Serializable並可以組合使用。

  • SerializeField : 表示變量可被序列化。衆所周知,公有變量可以在檢視面板中看到並編輯,而私有和保護變量不行。SerializeField與private,protected結合使用可以達到讓腳本的變量在檢視面板裏可視化編輯,同時保持它的私有性的目的。
  • HideInInspector : 將原本顯示在檢視面板上的序列化值隱藏起來。
  • NonSerialized :通過此方法可以將一個公有變量不序列化並且不顯示在檢視面板中。
  • Serializable:用在類的前面,表示該類可被序列化。

下面用一段代碼來舉例說明:

public class Test :Monobehavior
{
    public int  a;                               //序列化,顯示
    private int b;                               //不序列化,不顯示
    [SerializeField ] int c;                     //序列化,顯示
    [HideInInspector] public int d;              //序列化,不顯示
    [NonSerialized ] public int e;               //不序列化,不顯示
    public Test2 test2;                          //序列化,顯示(可序列化的部分)
}

[Serializable ]
public class Test2
{
     public int aa;
     private int bb;
}

我們新建一個Test腳本來驗證一下,輸入上述代碼後觀察檢視面板:

然後將掛在腳本的預製體用Sublime打開觀察序列化部分:

耶,成功了!

此外,Unity還有類SerializedObject,常用於編輯器模式下的工具或導入器中,修改資源或者Prefab的屬性。具體可參考官方文檔:

https://docs.unity3d.com/ScriptReference/SerializedObject.html

注意:並非所有的公有變量都是可以被序列化的。其中const,static是靜態的,屬於類而非對象,無法序列化。鏈表和字典在內存中的存儲是不連續的,也無法序列化。其中const,static,readonly的區別可參考文章:

http://www.cnblogs.com/suizhikuo/p/4739388.html

 

C#序列化

簡單介紹兩種常用的C#序列化操作(二進制方法和XML方法)

首先我們先定義一個可被序列化的類DemoClass

[Serializable]
public class DemoClass
{
    public int _id;
    public string _myName;
    public DemoClass(int id, string myName)
    {
        _id = id;
        _myName = myName;
    }
    public DemoClass()
    {
    }
    public void Output()
    {
        Debug.LogError(_id);
        Debug.LogError(_myName);
    }
}

它包含兩個公有變量id和name,一個含參的構造函數和一個默認構造函數(二進制不需要,XML必須), 一個用於顯示的輸出函數。

 

二進制方法(Binary Formatter)

序列化:新建或打開一個二進制文件,通過二進制格式器將對象demo寫入該文件中。

void WriteTest()
{
    DemoClass demo = new DemoClass (100, "RCD");
    FileStream fs = new FileStream ("demo.bin", FileMode.OpenOrCreate);
    BinaryFormatter bf = new BinaryFormatter ();
    bf.Serialize (fs, demo);
    fs.Close ();
    Debug.LogError ("write done");
}

反序列化:打開待反序列化的二進制文件,通過二進制格式器將文件解析成對象demo,並輸出到控制檯。

void ReadTest()
{
    FileStream fs = new FileStream("demo.bin", FileMode.Open);
    BinaryFormatter bf = new BinaryFormatter();
    DemoClass demo = bf.Deserialize(fs) as DemoClass;
    fs.Close();
    demo.Output();
}

 

耶,成功了!

注意:二進制方法可以序列化私有變量,不能序列化被[NonSerialized ]修飾的變量且類需要被[Serializable ]標識。

 

XML方法(XML Serializer)

序列化與反序列化與二進制方法十分類似。

void WriteTest()
{
    DemoClass demo = new DemoClass(100, "RCD");
    FileStream fs = new FileStream("demo.xml", FileMode.OpenOrCreate);
    XmlSerializer xml = new XmlSerializer(typeof(DemoClass));
    xml.Serialize(fs, demo);
    fs.Close();
    Debug.LogError("write done");
}

void ReadTest()
{
    FileStream fs = new FileStream("demo.xml", FileMode.Open);
    XmlSerializer bf = new XmlSerializer(typeof(DemoClass));
    DemoClass demo = bf.Deserialize(fs) as DemoClass;
    fs.Close();
    demo.Output();
}

 

耶,成功了!

注意:XML方法中類不需要[Serializable]標識,不能序列化私有變量,[NonSerialized]這個標識在該方法中無效。

區別:

  • 二進制方法:性能好,體積小。
  • XML方法:可讀性強,但體積較大,可在無其他環境時使用。

 

總結

本文介紹了Unity中序列化相關的關鍵字及其區別和用法,C#中兩種序列化與反序列化的方法。

希望大家在日常開發中合理使用SerializeField,不用濫用Public。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章