Unity3d+Json多对象数据读取与写入+JsonUtility实现

时间:2022-09-15 12:37:12

        这几天做自己的培训班的毕业项目,涉及到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();
    }

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