前言
Unity3D 的序列化機制是其核心功能之一,用于在編輯器和運行時之間持久化數據、管理場景狀態、處理預制體(Prefab)以及實現跨平臺兼容性。以下是其應用場景和基本原理的詳細解析:
對惹,這里有一個游戲開發交流小組,希望大家可以點擊進來一起交流一下開發經驗呀!
一、應用場景
- 場景(Scene)與預制體(Prefab)的保存與加載
- Unity 使用序列化將場景中的 GameObject、組件(Component)及其屬性保存為文本或二進制格式(如?
.unity
?場景文件或?.prefab
?文件)。 - 預制體的實例化和修改(如覆蓋屬性)依賴序列化機制。
- Inspector 面板的編輯
- 在編輯器中,組件的公有字段(或標記了?
[SerializeField]
?的私有字段)通過序列化機制暴露到 Inspector 面板,修改后的值會被序列化保存。
- ScriptableObject 數據持久化
- ScriptableObject 的數據通過序列化存儲為?
.asset
?文件,適用于游戲配置(如技能、物品屬性)。
- 資源熱更新與跨平臺兼容
- AssetBundle 中的資源(如材質、動畫)通過序列化實現跨平臺兼容,確保不同平臺加載時數據格式正確。
- 運行時狀態持久化
- 游戲存檔(如玩家進度、物品欄)可通過序列化(如?
JsonUtility
?或?BinaryFormatter
)保存到本地文件。
二、基本原理
1. 序列化的條件
Unity 的序列化遵循以下規則:
- 自動序列化的字段:
public
?字段(除非標記?[NonSerialized]
)。- 標記了?
[SerializeField]
?的私有/受保護字段。
- 不序列化的字段:
- 屬性(Property)、靜態字段、未標記?
[SerializeField]
?的私有字段。 - 標記了?
[NonSerialized]
?的字段。
- 屬性(Property)、靜態字段、未標記?
2. 序列化流程
- 編輯器序列化:
- 當場景或預制體保存時,Unity 將 GameObject 的層級結構和組件屬性轉換為 YAML 格式文本(可讀性高)。
- 示例:一個 Transform 組件的序列化結果:
Transform:m_ObjectHideFlags: 0m_Position: {x: 0, y: 0, z: 0}m_Rotation: {x: 0, y: 0, z: 0, w: 1}
- 運行時序列化:
- 使用?
JsonUtility.ToJson()
?或?BinaryFormatter
?將對象轉換為字符串或二進制數據。
- 使用?
3. 序列化深度
- Unity 支持深度序列化,遞歸處理對象及其子屬性。
- 例外:
- 引用類型(如?
UnityEngine.Object
?派生類)會被序列化為元數據(如 GUID 和文件ID),而非完整對象。 - 循環引用可能導致序列化失敗。
- 引用類型(如?
4. 自定義序列化
通過接口?ISerializationCallbackReceiver
,開發者可以在序列化前后執行邏輯:
public class CustomData : MonoBehaviour, ISerializationCallbackReceiver
{public Dictionary<string, int> stats = new Dictionary<string, int>();// 序列化前將 Dictionary 轉換為 List[SerializeField] private List<string> _keys;[SerializeField] private List<int> _values;public void OnBeforeSerialize(){_keys = new List<string>(stats.Keys);_values = new List<int>(stats.Values);}public void OnAfterDeserialize(){stats = new Dictionary<string, int>();for (int i = 0; i < _keys.Count; i++)stats.Add(_keys[i], _values[i]);}
}
三、技術細節與注意事項
- 版本兼容性
- 修改類結構(如刪除字段)可能導致反序列化失敗,舊數據可能丟失。
- 通過?
[FormerlySerializedAs("oldFieldName")]
?標記字段重命名,兼容舊數據。
- 性能優化
- 避免頻繁序列化大型數據結構(如長列表),尤其在移動端。
- 使用?
[Serializable]
?標記自定義結構體或類以支持序列化。
- 不可序列化的類型
- Unity 無法序列化接口(
interface
)、委托(delegate
)或非?UnityEngine.Object
?派生類。 - 解決方法:將接口轉換為具體類,或使用?
ScriptableObject
?封裝。
- Prefab 差異序列化
- 預制體實例的屬性覆蓋(如修改 Transform 的位置)通過序列化差異實現,保存為“覆蓋”數據而非完整副本。
四、調試與工具
- 查看序列化數據
- 在 Unity 編輯器中選擇?Assets > Open C# Project,查看?
.meta
?文件或 YAML 格式的預制體/場景文件。
- 序列化檢查工具
- 使用?
UnityEditor.Serialization
?命名空間中的工具(如?SerializedObject
?和?SerializedProperty
)在 Editor 腳本中調試序列化數據。
五、總結
Unity 的序列化機制是其數據驅動的核心,理解其規則和限制能幫助開發者:
- 避免數據丟失(如字段未正確序列化)。
- 優化資源管理(如合理使用 ScriptableObject)。
- 實現靈活的自定義數據持久化方案。
更多教學視頻
Unity3D?www.bycwedu.com/promotion_channels/2146264125