1.具體代碼
先貼代碼
using LitJson;
using System.IO;
using UnityEngine;/// <summary>
/// 序列化和反序列化Json時 使用的是哪種方案 有兩種 JsonUtility 不能直接序列化字典 ligJson可以序列化字典
/// </summary>
public enum JsonType
{JsonUtility,LitJson,Newtonsoft,
}/// <summary>
/// Json數據管理類 主要用于進行 Json的序列化存儲到硬盤 和 反序列化從硬盤中讀取到內存中
/// </summary>
public class JsonMgr : SingleTon<JsonMgr>
{public JsonMgr(){}//存儲Json數據 序列化public void SaveData(object data, string fileName, string directPath = "", JsonType type = JsonType.Newtonsoft){//確定存儲路徑string directoryPath = Application.persistentDataPath + "/" + directPath;string filePath = directoryPath + fileName + ".json";//序列化 得到Json字符串string jsonStr = "";switch (type){case JsonType.JsonUtility:jsonStr = JsonUtility.ToJson(data);break;case JsonType.LitJson:jsonStr = JsonMapper.ToJson(data);break;case JsonType.Newtonsoft:jsonStr = Newtonsoft.Json.JsonConvert.SerializeObject(data);break;}if (!Directory.Exists(directoryPath)){Directory.CreateDirectory(directoryPath);}//把序列化的Json字符串 存儲到指定路徑的文件中File.WriteAllText(filePath, jsonStr);}//讀取指定文件中的 Json數據 反序列化public T LoadData<T>(string filePath, JsonType type = JsonType.Newtonsoft) where T : new(){//數據對象T data = new T();//確定從哪個路徑讀取//首先先判斷 默認數據文件夾中是否有我們想要的數據 如果有 就從中獲取string path = Application.streamingAssetsPath + "/" + filePath + ".json";//先判斷 是否存在這個文件//如果不存在默認文件 就從 讀寫文件夾中去尋找if (!File.Exists(path))path = Application.persistentDataPath + "/" + filePath + ".json";//如果讀寫文件夾中都還沒有 那就返回一個默認對象if (!File.Exists(path))return data;//進行反序列化string jsonStr = File.ReadAllText(path);switch (type){case JsonType.JsonUtility:data = JsonUtility.FromJson<T>(jsonStr);break;case JsonType.LitJson:data = JsonMapper.ToObject<T>(jsonStr);break;case JsonType.Newtonsoft:data = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(jsonStr);break;}//把對象返回出去return data;}
}
2.使用示例
保存玩家數據
// 定義數據類
[Serializable]
public class PlayerData {public string name;public int level;
}// 保存數據
PlayerData data = new PlayerData { name = "Alice", level = 10 };
JsonMgr.Instance.SaveData(data, "player", "Save/", JsonType.Newtonsoft);
加載玩家數據
// 加載數據
PlayerData loadedData = JsonMgr.Instance.LoadData<PlayerData>("Save/player", JsonType.Newtonsoft);
Debug.Log($"Name: {loadedData.name}, Level: {loadedData.level}");
再補充一下一般我實際的使用方法
[System.Serializable] // 添加可序列化標簽
public class GameData
{public bool openLevel2 = false;public bool openLevel3 = false;public bool openLevel4 = false;public bool openLevel5 = false;public bool openCustom = false;
}public class LevelManager : MonoBehaviour
{// 添加當前游戲數據引用public GameData currentGameData;private const string SAVE_FILE_NAME = "GameSaveData";private void Start(){GameDataInit();}/// <summary>/// 讀取玩家信息,沒有則創建/// </summary>private void GameDataInit(){// 從JSON加載數據currentGameData = JsonMgr.Instance.LoadData<GameData>(SAVE_FILE_NAME);Debug.Log("持久化數據路徑: " + Application.persistentDataPath);// 如果沒有存檔數據,創建新數據if (currentGameData == null){currentGameData = new GameData();Debug.Log("創建新的游戲存檔");}}/// <summary>/// 保存游戲數據到JSON/// </summary>public void SaveGameData(){JsonMgr.Instance.SaveData(currentGameData, SAVE_FILE_NAME);Debug.Log("游戲數據已保存");}}
?把這個腳本設置成單例或者在合適的地方調用SaveGameData,存儲你想保存的類,這樣可以自動創建json自動讀取,只需要在合適的地方存檔就好了
3.核心功能
-
多方案支持
JsonType
?枚舉:支持三種 JSON 序列化/反序列化方案:Newtonsoft
(Json.NET):功能強大的第三方庫,支持復雜類型和更多特性。LitJson
:第三方庫,支持字典等復雜類型。JsonUtility
:Unity 內置方案,不支持字典等復雜類型。
-
數據存儲與讀取
SaveData
?方法:將對象序列化為 JSON 字符串并保存到指定路徑。LoadData<T>
?方法:從指定路徑讀取 JSON 文件并反序列化為對象。
4.代碼結構解析
1. 構造函數
public JsonMgr() { }
- 單例類的默認構造函數,無特殊邏輯。
2. 保存數據方法?SaveData
public void SaveData(object data, string fileName, string directPath = "", JsonType type = JsonType.Newtonsoft)
-
參數說明:
data
:要保存的對象。fileName
:文件名(不含?.json
?后綴)。directPath
:可選的子目錄路徑。type
:序列化方案(默認使用?Newtonsoft
)。
-
邏輯流程:
- 確定存儲路徑:
- 使用?
Application.persistentDataPath
(可讀寫路徑)構建完整路徑。 - 示例:
/Users/xxx/Library/Application Support/Unity/.../directPath/fileName.json
。
- 使用?
- 序列化:
- 根據?
type
?使用對應方案將對象轉換為 JSON 字符串。 JsonUtility
:JsonUtility.ToJson(data)
。LitJson
:JsonMapper.ToJson(data)
。Newtonsoft
:JsonConvert.SerializeObject(data)
。
- 根據?
- 創建目錄:若目錄不存在則創建。
- 寫入文件:使用?
File.WriteAllText(filePath, jsonStr)
?存儲數據。
- 確定存儲路徑:
3. 讀取數據方法?LoadData<T>
public T LoadData<T>(string filePath, JsonType type = JsonType.Newtonsoft) where T : new()
-
參數說明:
filePath
:文件路徑(不含?.json
?后綴)。type
:反序列化方案(默認使用?Newtonsoft
)。- 泛型約束?
where T : new()
:確保類型?T
?有無參構造函數。
-
邏輯流程:
- 優先從只讀路徑加載:
- 首先檢查?
Application.streamingAssetsPath
(只讀路徑,通常用于默認配置文件)。 - 如果文件不存在,嘗試從?
Application.persistentDataPath
(用戶數據路徑)加載。
- 首先檢查?
- 若文件不存在:返回默認的?
T
?實例(通過?new T()
?創建)。 - 反序列化:
- 根據?
type
?使用對應方案將 JSON 字符串轉換為對象。 JsonUtility
:JsonUtility.FromJson<T>(jsonStr)
。LitJson
:JsonMapper.ToObject<T>(jsonStr)
。Newtonsoft
:JsonConvert.DeserializeObject<T>(jsonStr)
。
- 根據?
- 優先從只讀路徑加載:
關鍵點分析
1. 路徑選擇與平臺兼容性
Application.persistentDataPath
:- 可讀寫路徑,適合保存用戶數據(如玩家進度、配置等)。
Application.streamingAssetsPath
:- 只讀路徑,通常用于打包后的默認資源(如初始配置文件)。
- 注意:在某些平臺(如 Android)上,
File.ReadAllText
?無法直接訪問此路徑的文件,需通過?UnityWebRequest
?或?WWW
?加載。當前代碼可能在此類平臺上拋出異常。
2. 默認值處理
- 若文件不存在,返回?
new T()
?創建的默認對象。適用于需要保證最小功能的場景(如游戲配置加載失敗時使用默認值)。
3. 異常處理缺失
- 當前代碼未處理文件讀寫或序列化/反序列化過程中可能出現的異常(如 IO 錯誤、格式錯誤)。建議添加?
try-catch
?塊并記錄日志。
4. 性能優化建議
- 異步操作:大量數據讀寫可能阻塞主線程,可改用異步方法(如?
File.ReadAllTextAsync
?/?File.WriteAllTextAsync
)。 - 緩存機制:對頻繁讀取的數據(如配置文件),可考慮緩存反序列化后的對象。