我以Dictionary类型作为案例存储的数据类型,向大家介绍如何将数据序列化,如何将数据存储为ScriptableObject,Json,Xml等形式
这是我个人开发游戏所自定义的数据类型,之后的操作中会使用到
[Serializable]
public class Skill : ScriptableObject
{
public string sname;
public SkillType type;
public int power;//威力
public int hitRate;//命中率
public int fullPP;//pp上限
public int curPP;//当前pp值
//属性
public PokeomonAttributes att;
}
public enum SkillType
{
物理,
特殊,
变化
}
private static Dictionary<int, Skill> allSkillDic = new Dictionary<int, Skill>();//allSkillDic是要存储的数据
ScriptableObject是unity自带的一个类,继承于UnityEngine.Object,可用于制作数据配置文件,或编辑器扩展便于可视化编辑,unity会自动将这个继承ScriptableObject的类序列化,可控性弱,但用于数据的加载是效率最高的。
由于ScriptableObject的使用要求,我们需要专门编写一个脚本作为所需要存储的数据类型
public class PokemonSkillsData :ScriptableObjectDictionary<int,Skill>
{
//需要专门为这几行代码编写一个cs文件
}
由于博主自己的游戏初始化需要加载大量的数据配置文件,博主选择编写一个泛型类减少代码量
由于Dictionary不是ScriptableObject支持可序列化的数据类型,实际序列化是我们要用2个List代替Dictionary序列化
using System;
using System.Collections.Generic;
using UnityEngine;
[Serializable]
public class ScriptableObjectDictionary :ScriptableObject
{
[SerializeField]
public List keys = new List();
[SerializeField]
public List values = new List();
protected Dictionary target;
public Dictionary Target
{
get
{
return target;
}
set
{
target = value;
keys = new List(Target.Keys);
values = new List(Target.Values);
}
}
}
存储
PokemonSkillsData serializationDictionary = ScriptableObject.CreateInstance();
serializationDictionary.Target=allSkillDic;
AssetDatabase.CreateAsset(serializationDictionary, "Assets/Resources/PokemonSkills.asset");
运行这几行代码可以看到Resources文件下出现了PokemonSkills.asset文件
读取
PokemonSkillsData myData = Resources.Load("PokemonSills");
allSkillDic = myData.Target;
SON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于ECMAScript的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C、C++、C#、Java、JavaScript、Perl、Python等)。这些特性使JSON成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成(一般用于提升网络传输速率)。
这里使用unity自带JsonUtility,
unity提供了ISerializationCallbackReceiver便于我们编写序列化类
[Serializable]
public class SerializationDictionary : ISerializationCallbackReceiver
{
[SerializeField]
public List keys = new List();
[SerializeField]
public List values = new List();
protected Dictionary target;
public Dictionary Target
{
get
{
return target;
}
set
{
target = value;
keys = new List(Target.Keys);
values = new List(Target.Values);
}
}
public void OnBeforeSerialize()
{
keys = new List(Target.Keys);
values = new List(Target.Values);
}
public void OnAfterDeserialize()
{
int count = Math.Min(keys.Count, values.Count);
target = new Dictionary(count);
for (int i = 0; i < count; ++i)
{
try
{
Target.Add(keys[i], values[i]);
}
catch(Exception e)
{
Debug.Log(e.Message);
}
}
}
}
json文件的读写速度相比ScriptableObject慢一些,但比xml快,文件大小比ScriptableObject大一些,比xml小
SerializationDictionary<int, Skill> sDictionary = new SerializationDictionary<int, Skill>();
sDictionary.Target = allSkillDic;
string json = JsonUtility.ToJson(sDictionary);
string path = Application.dataPath + "/Resources/PokemonSkills.json";
File.WriteAllText(path, json, Encoding.UTF8);
json = "";
StreamReader sr = new StreamReader(path);
json = sr.ReadToEnd();
SerializationDictionary<int, Skill> newdic = JsonUtility.FromJsonint, Skill>>(json);
LitJson是一个开源项目,可以简化序列化工作,不需要为每个类编写序列化类,轻松将一个object对象转换为json
注意:json里面的字段,自定义的对象一定要有
缺点:容易报错,需要转换数据类型
具体使用
去github找下下载,把LitJson文件下的cs文件集成一个类库项目,编译成dll,再通过unity的Import New Asset导入到项目中就能使用
Dictionary<string, Skill> dic = new Dictionary<string, Skill>() ;
foreach (var o in allSkillDic)
{
dic.Add(o.Key + "", o.Value);
}
string litjson = JsonMapper.ToJson(dic);
string path = Application.dataPath + "/Resources/PokemonSkills.json";
File.WriteAllText(path, litjson, Encoding.UTF8);
litjson = "";
StreamReader sr = new StreamReader(path);
litjson = sr.ReadToEnd();
Dictionary<string,Skill> dictionary= JsonMapper.ToObjectstring, Skill>>(litjson);
注意:
若包含Dictionary结构,则key的类型必须是string,而不能是int类型,否则无法正确解析!
若需要小数,要使用double类型,而不能使用float,可后期在代码里再显式转换为float类型。
Newtonsoft.Json,一款.NET中开源的Json序列化和反序列化类库(下载地址http://json.codeplex.com/,https://github.com/SaladLab/Json.Net.Unity3D/releases)。
优点:灵活,不需要和json字段一对一
使用
string json = JsonConvert.SerializeObject(allSkillDic);
string path = Application.dataPath + "/Resources/PokemonSkills.json";
File.WriteAllText(path, json, Encoding.UTF8);
json = "";
StreamReader sr = new StreamReader(path);
json = sr.ReadToEnd();
Dictionary dictionary = JsonConvert.DeserializeObject>(json);
xml解析速度相当慢,文件也相当大,可读性强,在编写编辑器扩展读写数据相当频繁地被使用。
这里使用系统自带的xml解析,需要编写复杂的序列化类
首先需要继承Dictionary
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Xml.Serialization;
[Serializable]
public class XmlDictionary:Dictionary, IXmlSerializable
{
XmlSerializer ks = new XmlSerializer(typeof(TKey));
XmlSerializer vs = new XmlSerializer(typeof(TValue));
#region 构造函数
public XmlDictionary()
: base()
{
}
public XmlDictionary(IDictionary dictionary)
: base(dictionary)
{
}
public XmlDictionary(IEqualityComparer comparer)
: base(comparer)
{
}
public XmlDictionary(int capacity)
: base(capacity)
{
}
public XmlDictionary(int capacity, IEqualityComparer comparer)
: base(capacity, comparer)
{
}
protected XmlDictionary(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
#endregion 构造函数
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
bool wasEmpty = reader.IsEmptyElement;
reader.Read();
if (wasEmpty)
return;
while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
{
reader.ReadStartElement("Item");
reader.ReadStartElement("Key");
TKey k = (TKey)ks.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement("Value");
TValue v = (TValue)vs.Deserialize(reader);
reader.ReadEndElement();
Add(k, v);
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
foreach (TKey key in Keys)
{
writer.WriteStartElement("Item");
writer.WriteStartElement("Key");
ks.Serialize(writer, key);
writer.WriteEndElement();
writer.WriteStartElement("Value");
TValue value = this[key];
vs.Serialize(writer, value);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
}
string path = Application.dataPath + "/Resources/";
XmlDictionary<int, Skill> xmlDictionary = new XmlDictionary<int, Skill>(allSkillDic);
using (FileStream fileStream = new FileStream(path+ "PokemonSkills.xml", FileMode.Create))
{
XmlSerializer xmlFormatter = new XmlSerializer(typeof(XmlDictionary<int,Skill>));
xmlFormatter.Serialize(fileStream, xmlDictionary);
}
xmlDictionary.Clear();
//反序列化获取存储的dictionary
using (FileStream fileStream = new FileStream(path + "PokemonSkills.xml", FileMode.Open))
{
XmlSerializer xmlFormatter = new XmlSerializer(typeof(XmlDictionary<int, Skill>));
xmlDictionary = (XmlDictionary<int, Skill>)xmlFormatter.Deserialize(fileStream);
}