这些天在写交易系统的时候,需要用到很多物品,它们还是有分类的,不同的有不同的描述。自己第一个想到的就是定义一个物品类,在一个结构体里把所有需要的属性(类别、名字、描述、加成buff啥的)都放进去,大概又可以写好多行了2333。这种方式也是我之前做过的方式,但这一次,博主多思考了一下,能不能把这些可修改的信息从代码中抽离出来,作为一个外部文件,以任何人都好理解和修改的方式存储。博主再一想,emmmmm…外部文件,先想到的就是表格,txt存储。再一想,这读取的时候必然会涉及到字符串、空格什么的处理的,博主觉得不够明朗简洁。就到网上去查阅了关于简洁快速的unity中数据存储的方式——JSON。 关于它,网上的博客教程都不尽相同,而且很乱。在这里,我整合看过的知识,结合自己遇到的问题提出相应的讲解方法,希望大家能够有所收获吧。
首先来介绍下,【摘自百度百科】
JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。它基于 ECMAScript (w3c制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
很惊讶的是,它在游戏服务器间的传输中已经算的是常用的处理方式了。好了,接下来进入正题:
•数据在键值对中
•数据由逗号分隔
•花括号保存对象
•方括号保存数组
以上,就完成了基本的了解和准备工作了。
JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。
Json创建中writer.WriteObjectStart ();就等同于“{”,writer.WriteObjectEnd ()就等同于“}”,最后要转换成string型,json = writer.ToString ();。解析Json时,JsonData jsonData = JsonMapper.ToObject (json);注意复合Json解析完了是一个数组。
JsonData实现的接口如下:
IJsonWrapper, IList, ICollection, IEnumerable, IOrderedDictionary, IDictionary, IEquatable
string s = "[{'name':'lisi'},{'name':'zhangsan'}]";
string a = "{'name':'aaa'}";
JsonData[] jarr = JsonMapper.ToObject(s);
print(jarr. IsArray);//返回true
if(jarr.IsArray){
foreach(JsonData jd in jarr){
print(jd["name"]);//返回结果: lisi
// zhangsan
}
}
JsonData jdata = JsonMapper.ToObject(s);
print(jdata.IsArray);//返回true
if (jdata.IsArray)
{
for (int i = 0; i < jdata.Count;i ++ )
{
print(jdata[i]["name"]);//返回的结果: lisi
// zhangsan
}
}
JsonData j = JsonMapper.ToObject(a);
print(j.IsArray);//返回false
print(j["name"]);//返回aaa
从上面的示例可以看出JsonData是否能以数组的方式访问需看json字符串返回的是否是数组类型的.对象内有一个数组.分别需要用到一个Json对象模型(JsonObjectModel)和一个Json数组模型(JsonArrayModel)来接收这两种Json数据
示例展示了最基本得JsonData用法: 创建一个JsonData通常由JsonMapper的ToObject方法,这个方法有3个重载:
JsonMapper.ToObject(JsonReader reader);
JsonMapper.ToObject(string json);
JsonMapper.ToObject(System.IO.TextReader reader);
其中JsonReader类也是一个读取json字串的类,不过它是按行的方式读取,不能像key-value的方式读取json的值,第二个是最常见的创建JsonData的方式,它只需提供一个json字串即可,第三个是读取一个包含json字符的文本流来创建一个JsonData
JsonMapper中还有一个ToObject方法:public static T ToObject();当然它也有三个重载,同上
好了,现在也有了大致的了解,开始介绍使用流程啦。
首先,要书写自己的外部文件【用来读取和存储的】,以.json格式
注明:就是在桌面上先新建一个记事本文档,在另存为修改为所有文件后,把名字改成.json,如图:
保存成功后,就会是这样色儿的——
其中保存的数据格式是有点像枚举类加数组的风格的,每个对象以 名字: 再以“{}”各自包裹着,之间以“,”隔开,最外层是“【】”
放一张其他博主的代码图片(其中涉及到了多个对象的情况 cards就是一个对象啦)
而我写的是没有区分外面的大分别的,如下:【仅截取一部分】
以上,就写完了自己的外部json文件,接下来就是要按照一定的格式为你的外部文件写一个解析类!
解析类如下写法:
public class Skill
{
public int id { set; get; }
public string name { set; get; }
public int damage { set; get; }
public override string ToString()
{
return string.Format("id:{0};name:{1};damage:{2}", id, name, damage);
}
}
博主放一下自己的解析类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Text;
public class Item
{
public int ID { get; set; }
public string Name { get; set; }
public ItemQuality Quality { get; set; }
public ItemType Type { get; set; }
public int Capacity { get; set; }//每一个格子中可存放物体的最大容量
public string Description { get; set; }
public int BuyPrice { get; set; }
public int SellPrice { get; set; }
public string Sprite { get; set; }//查找精灵路径
//物品类的构造函数
public Item()
{
this.ID = -1;//表示这是一个空的物品类
}
public Item(int id, string name, ItemType type, ItemQuality quality, string description, int capaticy, int buyPrice, int sellPrice, string sprite)
{
this.ID = id;
this.Name = name;
this.Type = type;
this.Quality = quality;
this.Description = description;
this.Capacity = capaticy;
this.BuyPrice = buyPrice;
this.SellPrice = sellPrice;
this.Sprite = sprite;
}
//关于物品各个类型的详细分类
public enum ItemType
{
luxury,//奢饰品,包括的是各个地方的特产
necessity//必需品,包括食物、木柴等生活用品
}
public enum ItemQuality
{//同一类型物品之间按照质量指标来规定价钱
Common,
Rare,
Legendary//传奇的
}
//把类中的数据转换为字符串,在提示框中显示
public virtual string ToString()
{
string strItemType = "";
switch (Type)
{
case ItemType.luxury:
strItemType = "奢侈品";
break;
case ItemType.necessity:
strItemType = "必需品";
break;
}
string strItemQuality = "";
switch (Quality)
{
case ItemQuality.Common:
strItemQuality = "一般材质";
break;
case ItemQuality.Rare:
strItemQuality = "稀有材质";
break;
case ItemQuality.Legendary:
strItemQuality = "传奇材质";
break;
}
string color = ""; //用于设置提示框各个不同内容的颜色
switch (Quality)
{
case ItemQuality.Common:
color = "white";
break;
case ItemQuality.Rare:
color = "yellow";
break;
case ItemQuality.Legendary:
color = "blue";
break;
}
string text = string.Format("{1} \n介绍:{2} \n容量:{3} \n物品类型:{4} \n物品质量:{5} \n购买价格$:{6} \n出售价格$:{7} ", color, Name, Description, Capacity, strItemType, strItemQuality, BuyPrice, SellPrice);
return text;
}
}
注意事项:解析的属性必须与json中的属性完全一致,否则无法获取数据;此处为了获得输出结果重写tostring方法。
使用LitJson进行解析
//将解析的文本读入一个字符串,如果是unity也是一样
string str = File.ReadAllText(“Skill.Json”);
//要解析的是一个Skill类型的对象数组,使用泛型解析
Skill[] skillList = JsonMapper.ToObject
public class JsonDeserialize : MonoBehaviour
{
void Start( )
{
//获取Json文件
TextAsset jsonData = Resources.Load("JsonData");
JsonObjectModel jsonObject = JsonMapper.ToObject(jsonData.text);
foreach (var info in jsonObject.infoList)
{
Debug.Log(info.panelTypeString+" "+info.path);
}
}
}
本人偶然用到了JSONObject,如下
itemList = new List<Item>();
//文本为在Unity里面是 TextAsset类型
TextAsset itemText = Resources.Load<TextAsset>("message");
string itemsJson = itemText.text;//物品信息的Json格式
JSONObject j = new JSONObject(itemsJson);
foreach (JSONObject temp in j.list)
{ ......}
第一次就出现了报错,原因是JSONObject中没有实现这些方法的代码,所以你可以选择自己写来实现里面存一个链表读取数据什么的,也可以去网上找开源的程序。
注意:当程序提醒你,json数据不能转换为什么什么数据的时候,大胆的强制转换就好啦。
好了,博主的干货就到这里啦,再分享几个链接,讲的真的好好,也是博主淘了好久找到的,希望可以助于理解啦。
开启吧魔法阵1号ヾ(=・ω・=)o
开启吧魔法阵2号٩(๑>◡<๑)۶