Unity3d+Json多物件資料讀取與寫入+JsonUtility實現
這幾天做自己的培訓班的畢業專案,涉及到Json的讀取與寫入,本來想用LitJson的,後來發現5.3以後的版本有自帶的實現,而且很方便,配合System.IO就可以方便的實現,網上這方面資料也不少,但這裡給出更具體的實現,例如Json檔案中不只有一個物件,涉及多物件的時候怎麼辦,適合初學者看看。
1.首先看Json檔案
//////////////// testJson.json ////////////////////
{
"inforList": [{"sceneName": "scene0",
"version": 1.0,
"score": 250
}, {
"sceneName": "scene1",
"version": 1.0,
"score": 150
}, {
"sceneName": "scene2",
"version": 1.0,
"score": 400
}]
}
這個檔案位置是在 Asset/Resources/ 資料夾下面的
////////////////////////////////////
2. 對應的Json資料類
//////////////////////////// PlayerInfo.cs //////////
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class PlayerInfo {
public List<InfoItem> inforList;
public string SaveToString()
{
return JsonUtility.ToJson(this);
}
public void Load(string savedData)
{
JsonUtility.FromJsonOverwrite(savedData, this);
}
}
[System.Serializable]
public class InfoItem {
public string sceneName;
public float version;
public int score;
}
/*
這裡聲明瞭一個連結串列,對應json檔案中的 “inforList”,名字一定要對上
內部物件類 即InfoItem 類一定要加序列化,用了C#裡面的序列化,具體可以看
官方文件
*///////////////////////////////////////////////////////
3.然後是工具類
/////////////////// JsonTools.cs /////////////////
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
public static class JsonTools {
//這裡沒什麼好說的,將類資料儲存到JSON中,形參playerinfo,可有可無,
//我是為了減少記憶體分配的次數
float member2 = 1.0f, int member3 = 0)
{
if (playerinfo != null)
{
playerinfo.inforList[index].sceneName = member1;
playerinfo.inforList[index].version = member2;
playerinfo.inforList[index].score = member3;
string saveString = playerinfo.SaveToString();
WriteFile(Application.dataPath + "/Resources/" + "testJson.json", saveString);
return playerinfo;
}
else {
Debug.LogError("PlayerInfo instance error");
return null;
}
}
public static void WriteFile(string path, string content)
{
if (Directory.Exists(path))
{
File.Delete(path);
}
File.WriteAllText(path, content);
}
//從json檔案中讀取資料,並返回資料類
public static PlayerInfo ReadDataFromJson(string jsonFileName){
if (!File.Exists(Application.dataPath + "/Resources/" + jsonFileName))
{
Debug.LogError("path error");
return null;
}
StreamReader sr = new StreamReader(Application.dataPath +
"/Resources/" + jsonFileName);
string json = sr.ReadToEnd();
//這裡很重要,當你想delete檔案時候,如果不加close()就會報錯。
//這是因為讀取內容的時候沒有close(),就破壞了共享。
//而且using system。IO很消耗資源,當你讀取內容之後,要立即close()
//IOException:Sharing Violation on Path*************
//首先我們分析下它的語義,sharing是共享,violation簡單的意思就是破壞,
//所以大致意思就是:在******** 位置的共享被破壞。
sr.Close();
PlayerInfo playerinfo = new PlayerInfo();
if (json.Length > 0)
{
playerinfo = JsonUtility.FromJson<PlayerInfo>(json);
}
return playerinfo;
}
}
////////////////////////////////////////////////////
4. 最後 打包成exe檔案時,要把json檔案複製到對應data資料夾中,不然遊戲進行不下去
這裡同樣給出實現例子
///////////////////////////////////////////////////////////////////////////
sceneIndex = SceneManager.GetActiveScene().buildIndex - 1;
playerInfo = JsonTools.ReadDataFromJson("testJson.json");
sceneScore = playerInfo.inforList[sceneIndex].score;
score.text = "score : " + sceneScore.ToString();
///////////////////////////////////////////////////////////////////////////
void saveScore(int number) {
string sceneName = "scene" + sceneIndex.ToString();
playerInfo = JsonTools.ReadDataFromJson("testJson.json");
JsonTools.saveToJson(playerInfo, sceneIndex, sceneName, 1.0f, number);
sceneScore = playerInfo.inforList[sceneIndex].score;
score.text = "score : " + sceneScore.ToString();
}
//////////////////////////////////////////////////////////////////////////