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