1. 程式人生 > >Unity3d+Json多物件資料讀取與寫入+JsonUtility實現

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,可有可無,

     //我是為了減少記憶體分配的次數

    public static PlayerInfo saveToJson(PlayerInfo playerinfo,int index, string member1, 
        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();
    }

//////////////////////////////////////////////////////////////////////////