前言
- 本内容为本人原创提供
- 本内特为学习者提供原创完整的工程源码下载,可参考学习或其他用途。
- 本内容从武器相关属性出发,对数据存取操作,一步一步推进,能直观感受。
- 如果后续有其他的存取游戏数据的方式,将继续提供给大家借鉴参考,希望能协助大家完成自己项目。
目录
写着写着就这么多了,可能不是特别全,不介意费时就看看吧。有时间还会接着更新。
一、什么是json
JSON是数据交换格式,于2000年被定义出基本语法和数据结构模式,13年后正式定义了JSON的数据交换格式,详细描述了JSON的语法和结构。它用于服务器与网络应用程序,具有较高的传输效率,使得其广泛运用。
二、json全认识
先上一段 json 数据结构
{
"weapon_list": [
{
"weapon_id": "00001",
"weapon_lv": "1",
"weapon_name": "伏魔剑",
"weapon_atc": 30,
"weapon_def": 1,
"weapon_money": 100,
"weapon_skillidlist": [
{
"skil_id1": "00001",
"skil_id2": "00003",
"skil_id3": ""
}
]
},
{
"weapon_id": "00002",
"weapon_lv": "1",
"weapon_name": "令月剑",
"weapon_atc": 55,
"weapon_def": 1,
"weapon_money": 500,
"weapon_skillidlist": [
{
"skil_id1": "00001",
"skil_id2": "",
"skil_id3": ""
}
]
},
{
"weapon_id": "00003",
"weapon_lv": "1",
"weapon_name": "云征剑",
"weapon_atc": 75,
"weapon_def": 1,
"weapon_money": 800,
"weapon_skillidlist": [
{
"skil_id1": "00002",
"skil_id2": "00005",
"skil_id3": ""
}
]
},
{
"weapon_id": "00004",
"weapon_lv": "1",
"weapon_name": "木舞剑",
"weapon_atc": 125,
"weapon_def": 1,
"weapon_money": 1700,
"weapon_skillidlist": [
{
"skil_id1": "00003",
"skil_id2": "00004",
"skil_id3": "00005"
}
]
},
{
"weapon_id": "00005",
"weapon_lv": "1",
"weapon_name": "蟲羽剑",
"weapon_atc": 150,
"weapon_def": 1,
"weapon_money": 2100,
"weapon_skillidlist": [
{
"skil_id1": "00001",
"skil_id2": "00007",
"skil_id3": ""
}
]
}
]
}
1、键和值
“xxx”:“yyy”, 左边是一条键值
- “xxx”是“键”,“yyy”是“值”,其中有“:”分开,
- ,是分隔下一对键值的符号,但是如果是最后一行键值,不用该符号。
2、{ } 中的对象
{ } 是包括对象的符号,其中可以放键值,或者数组,值之间用逗号“,”分隔。
3、[ ] 数组
由单个或者多个键值或者数组组合,用方括号 [ ] 包围,值之间用逗号“,”分隔。
4、两种不同结构写法
"weapon_skillidlist": [
{
"skil_id1": "00001",
"skil_id2": "",
"skil_id3": ""
}
]
"weapon_skillidlist":
[
{
"skil_id1": "00001",
},
{
"skil_id2": "",
},
{
"skil_id3": ""
},
]
根据自己喜好或者眼缘选一个,这里我们就选第一个了。
5、注意事项
- 初学json数据格式会比较晕,这里推荐一个检测json文本是否合格的网站 json格式检测网址
- 另外json数据中的空格是被忽略的。
- 最后,json文档是以.json为后缀。
三、unity实战
本次实战采用武器属性单元展开,对武器属性进行存档和读档操作。
1、起始工作
1.1、unity对json操作的准备工作
我们采用 Newtonsoft.Json 组件对json进行数据操作,需要导入该组件。Newtonsoft.Json 也是.net开发中常用的网络数据解析dll,效率高,所以选它了。
导入之后,文件夹情况是这样
1.2、c#对操作的起始工作
解析json需要引用
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
对文件操作引用
using System.IO;
1.3、玩家属性:
首先,把武器内容属性规范好,可以创建武器结构体,或者类。如果数据多,并且比较复杂,可以选择类,我这里选择创建一个武器类
public class Weapon
{
public int weapon_id { get; set; }
public int weapon_lv { get; set; }
public string weapon_name { get; set; }
public int weapon_atc { get; set; }
public int weapon_def { get; set; }
public int weapon_money { get; set; }
public List<WeaponSkill> weapon_skillidlist { get; set; }
}
补充一个知识点:如果是用 JsonUtility 操作 json 数据 那就不要用 get set 方法,否则读取不到数据
注意:第一个 { } 是根对象,我们需要再建一个类,将所有武器类都装进去
public class JsonRoot
{
public List<Weapon> weapon_list { get; set; }
}
weapon_list 是json文件中的根对象,这里和jsonroot中的变量对象名称必须保持一样。否则会报错:
ArgumentNullException: Value cannot be null.
同时把 weapon_skillidlist 创建出来
public class WeaponSkill
{
public string skil_id1 { get; set; }
public string skil_id2 { get; set; }
public string skil_id3 { get; set; }
}
这里是一个一个装有技能 ID 的类,如果设计了技能系统,可以根据这些变量值去解析对应的技能。当然,我们这课是没有技能系统,只声明了一个技能名称作为展示。
最终,我们创建了三层结构,JsonRoot 里面的 weapon_list 对应json根对象,Weapon 作为json主要的对象,weapon_skillidlist 则是对应最后一个 WeaponSkill 里的对象。
注意,这三个类的变量名与json里面的键对象名称都是一致。
2、创建json文件
json文件数据结构比较复杂,我们采用备份原始数据,再复制一份可以随时修改和保存的文件。
2.1、创建文件路径
private string jsonsourcePath = Application.dataPath + "/Save/basic/gameJson(备份勿删).json";
private string jsonPathDestination = Application.dataPath + "/Save";
private string jsonPath = Application.dataPath + "/Save/gameJson.json";
2.2、创建文件
//序创建一个Json表,将默认文件拷贝到或者覆盖
public void CreateJsonDoc()
{
string newFileName = "gameJson.json"; // 新文件名
// 目标文件的完整路径
string jsdestinPath= Path.Combine(jsonPathDestination, newFileName);
// 复制文件到新路径,并重命名
File.Copy(jsonsourcePath, jsdestinPath, true); // true 表示如果目标文件存在,则覆盖它
}
由 jsonsourcePath 路径下的文件复制并覆盖到 jsonPathDestination 下,这个新文件的名字叫做 "gameJson.json"。
其实是把 jsonPath 文件覆盖了,而这个文件就是我们要存和取的文件。
3、保存的json数据
StreamReader reader = new StreamReader(jsonPath, Encoding.UTF8);
读取文件流
public void SaveJsonDoc()
{
if (Gamemanager.Instance.weaponList.Count <= 0)
return;
string str = JsonConvert.SerializeObject(Gamemanager.Instance.jsonRoot, Formatting.Indented);
File.WriteAllText(jsonPath, str);
}
}
我们只需要对 JsonRoot 类中的 weapon_list 变量进行序列化,那么就可以转为一串字符进而保存 json 了。
weapon_list 里面的值都是读取而来。
4、读取json数据
public void ReadJsonDoc()
{
StreamReader reader = new StreamReader(jsonPath, Encoding.UTF8);
string jsonContent = reader.ReadToEnd();
Gamemanager.Instance.jsonRoot = new JsonRoot();
Gamemanager.Instance.jsonRoot = JsonConvert.DeserializeObject<JsonRoot>(jsonContent);
Gamemanager.Instance.weaponList = new List<Weapon>(Gamemanager.Instance.jsonRoot.weapon_list);
reader.Close();
reader.Dispose();
}
DeserializeObject流文件后,记得关闭释放,不然会其他操作报错
IOException: Sharing violation on path C:\pro\My project (2)\Assets\Save\gameJson.json
取出文件流,由 DeserializeObject<JsonRoot> 反序列并赋值给 JsonRoot 类中的 weapon_list。
只要读到一个根对象,就能得到全部json数据,就这么简单。
只要类的变量名和json中的对象(键)名称保持一致,基本上就保证成功了。
五、运行图示
六、总结
- json数据结构中,注意每个同级别键值的最后一条键值不需要加“ , ”。
- 解析的类中的变量名一定要与数据结构中的对象(键)名一致。
- 游戏是复杂的数据结构,做好类结构,变量结构,争取只用一个类读取全部的json数 据。
- 清晰的类与数据结构,能在做游戏数据时不会干扰到自己的开发。
- 如果有问题,去检测数据结构的网址看看。