文章目錄
- 前言
- 框架獲取與集成
- 使用方法
- 基本配置
- 自動生成序列化方法
- 實戰示例
- 技術原理與優勢
- 二進制序列化的優勢
- SJBinary的設計特點
- 最佳實踐建議
- 適用場景
- 總結
前言
在Unity開發過程中,與后臺交互時經常需要處理大型數據文件。當遇到一個近2MB的本地JSON文件需要解析為對象時,使用傳統的JSON解析方案(無論是Unity自帶的JsonUtility還是流行的Newtonsoft Json.NET)都面臨著顯著的性能瓶頸。在實測中,這些方案解析時間可能長達3秒以上,即使經過優化也需要約1.5秒,同時還伴隨著大量的GC(垃圾回收)開銷。
針對這一問題,我們開發了一個高性能的二進制序列化框架——SJBinary。經過測試,該框架在性能表現上超越了市面上多數JSON框架和Unity自帶的BinaryFormatter,接近Protobuf-net的性能水平,雖然略低于MessagePack,但其集成簡單、代碼量小的特點使其成為Unity項目中數據序列化的優秀選擇。
實測數據顯示,使用SJBinary創建10萬個對象并序列化為二進制數據僅需480多毫秒,反序列化過程僅需340多毫秒,性能提升顯著。
提示:二進制數據處理本質上比JSON處理更加高效,因為它避免了文本解析的復雜過程,直接使用二進制格式表示數據。
框架獲取與集成
sjgenerate下載鏈接
1.點擊上面鏈接即可下載
2.下載完后將SjBinary拖入項目即可
3.定義類并添加注解[SJBinary]及實現接口ISJSerializable
使用方法
基本配置
[SJBinary]
public class A : ISJSerializable
{public string name;public int age;public void Deserialize(SJBinaryReader reader){throw new System.NotImplementedException();}public void Serialize(SJBinaryWriter writer){throw new System.NotImplementedException();}
}
自動生成序列化方法
- 點擊Unity頂部菜單欄:Tools -> SJBinary -> Generate Methods
- 系統將自動實現Deserialize和Serialize方法
生成的類結構如下:
[SJBinary]
public class B : ISJSerializable
{public string name;public int age;public void Serialize(SJBinaryWriter writer){writer.Write(this.name);writer.Write(this.age);}public void Deserialize(SJBinaryReader reader){this.name = reader.ReadString();this.age = reader.ReadInt32();}
}
實戰示例
以下是一個完整的使用示例,展示了如何在Unity中使用SJBinary進行高效序列化和反序列化:
public class ErJinZhiSample : MonoBehaviour
{//優化前497 343msprivate List<byte[]> serializedData = new List<byte[]>();public List<TestA> deserializedObjects = new List<TestA>();private const int count = 100000;public Button btnLoad;public Button btnCreate;// 復用的 readerprivate SJBinaryReader reader;void Start(){btnLoad.onClick.AddListener(TestLoad);btnCreate.onClick.AddListener(TestCreate);}void TestCreate(){serializedData.Clear();var writer = new SJBinary.SJBinaryWriter(1024); // 可復用緩沖區Stopwatch sw = Stopwatch.StartNew();for (int i = 0; i < count; i++){writer.Reset(); // 復用緩沖區TestA obj = new TestA{age = i,name = $"Name_{i}",time = DateTime.Now.Ticks,actions = "Run,Jump",actionsList = new List<string> { "Run", "Jump", "Walk" },ids = new List<int> { 1, 2, 3 },pads = new List<int> { 10, 20, 30 }};obj.Serialize(writer);// 保存二進制數據(注意這里保存的是 ArraySegment 以避免復制)serializedData.Add(writer.GetBytes());}sw.Stop();UnityEngine.Debug.Log($"[Create] Created and serialized {count} objects in {sw.ElapsedMilliseconds} ms");}void TestLoad(){deserializedObjects.Clear();Stopwatch sw = Stopwatch.StartNew();for (int i = 0; i < count; i++){byte[] data = serializedData[i];// 復用 readerif (reader == null)reader = new SJBinary.SJBinaryReader(data);elsereader.SetBuffer(data, 0, data.Length);TestA obj = new TestA();obj.Deserialize(reader);deserializedObjects.Add(obj);}sw.Stop();UnityEngine.Debug.Log($"[Load] Deserialized {count} objects in {sw.ElapsedMilliseconds} ms");}
}
技術原理與優勢
二進制序列化的優勢
1.高效性能: 二進制格式避免了文本解析的復雜性,直接讀寫內存數據
2.緊湊體積: 二進制數據通常比等效的JSON文本小30%-50%
3.低GC開銷: 通過緩沖區復用和零拷貝技術大幅減少垃圾回收壓力
SJBinary的設計特點
1.簡單集成: 只需添加注解和接口實現,無需復雜配置
2.代碼生成: 提供工具自動生成序列化代碼,減少手動編寫錯誤
3.緩沖區復用: 支持讀寫緩沖區的復用,極大減少內存分配
4.類型安全: 編譯時檢查類型一致性,避免運行時錯誤
最佳實踐建議
1.適當初始化緩沖區大小: 根據典型數據大小初始化緩沖區,避免頻繁擴容
2.復用讀寫器實例: 特別是在循環中處理多個對象時
3.處理版本兼容性: 當數據結構變化時,需要考慮向后兼容性策略
4.異常處理: 在序列化和反序列化過程中添加適當的異常處理機制
適用場景
SJBinary特別適用于以下場景:
- 需要頻繁序列化/反序列大量數據的游戲
- 對性能敏感的網絡通信應用
- 需要持久化大量游戲狀態的單機游戲
- 需要快速加載大型配置文件的應用程序
總結
SJBinary為Unity開發者提供了一個簡單易用且高性能的二進制序列化解決方案。通過其簡潔的API設計和高效的實現,它能夠顯著提升數據處理的性能,同時保持較低的內存開銷。對于需要處理大量數據的Unity項目,SJBinary是一個值得考慮的輕量級解決方案。
如果您在使用過程中有任何建議或問題,歡迎在評論區留言反饋。我們將持續優化和改進這個框架,以滿足更多開發場景的需求。