概述
数据序列化和持久化
序列化:将对象或者数据结构转化成特定的格式,使其可在网络中传输,或者可存储在内存或者文件中。
持久化:将数据存储到可永久保存的存储介质中(如磁盘)。
序列化和反序列化
序列化:将类对象信息转换为可保存或传输的格式的过程。
反序列化:与序列化相对,将保存或传输过来的格式转换为类对象的过程。
为什么需要关注序列化?
-
数据持久化:保存玩家存档、配置数据、场景状态。
-
Inspector交互:在编辑器中直观调整脚本参数。
-
跨平台兼容:通过标准格式(如JSON)实现不同平台间的数据交换。
-
性能优化:合理的序列化策略可减少内存占用和加载时间。
PlayerPrefs
常用接口
SetInt | 保存整型数据 |
GetInt | 读取整型数据 |
SetFloat | 保存浮点型数据 |
GetFloat | 读取浮点型数据 |
SetString | 保存字符串数据 |
GetString | 读取字符串数据 |
DeleteAll | 删除所有保存的数据(谨慎使用) |
DeleteKey | 删除指定键的数据 |
HasKey | 判断本地是否有保存指定键对应的数据 |
Save | 保存所有修改的数据 |
优缺点
优点 | 简单易用 |
缺点 | 1、只能支持三种类型的数据存取:int\float\string 2、数据安全型低 |
适用范围
适合用来存储暂时性数据:
1、玩家偏好设定
2、简单的数据
3、游戏原型制作时临时存储方案
Json
常用接口
JsonUtility
JsonUtility是Unity内置的JSON处理工具,不支持Dictionary、Query、Stack等集合。
1、object转json字符串
var str = JsonUtility.ToJson(obj);
2、object转json字符串,格式化打印,看起来更直观
var str = JsonUtility.ToJson(obj);
3、json字符串转指定类型
Student result = JsonUtility.FromJson<Student>(str);
LitJSON
需要将LitJSON.dll文件放入到Plugins文件夹下,支持Dictionary
// 将数据对象转为字符串
var str = LitJson.JsonMapper.ToJson(obj);
//json字符串转为对象
Student result = LitJson.JsonMapper.ToObject<Student>(str);
提示
1、有些数据JsonUtility可以序列化而LitJSON不可以;有些数据LitJSON可以而JsonUtility不可以,所以联合使用可达奇效。
2、将获取的json字符串写入到一个文件中,并保存到Application.persistentDataPath指定的自定义文件夹下。读取的时候从该路径下就可以读取保存的数据,从而实现数据持久化。
优缺点
优点 | 1、方便人类阅读和编写 2、使用范围广泛,支持多种主流编程语言 3、轻量级,易于网络传输、解析和生成 |
缺点 | 1、数据安全型低 2、文件读写时效率较低 3、内存和硬盘占用空间大 |
适用范围
1、网络数据交换
2、存储不是很重要并且需要大量读取和修改的数据
3、玩家偏好设置
二进制
通过将各类型变量转换为字节数组,再将字节数组直接存储到文件中。
常用接口
处理非字符串数据
支持整型、浮点型、字符型、布尔型
int value = 365;
//数据转成字节数组
var array = BitConverter.GetBytes(value);
//将字节数据转成指定数据
var result = BitConverter.ToInt32(array);
处理字符串数据
var str = "好好学习,天天向上";
//字符串转byte数组
Byte[] array = Encoding.UTF8.GetBytes(str);
//byte数组转字符串
string result = Encoding.UTF8.GetString(array);
处理类对象
注意:如果要使用C#自带的序列化二进制方法,申明类时需要添加[System.Serializable]
特性。如果没有这个特性,BinaryFormatter 将无法处理该类
[Serializable]
public class Student
{public int id;public string name;public List<int> dataList;public Dictionary<string, int> scoreDic;
}
第一种方法
/****************************序列化(二进制文件)****************************/
using (MemoryStream ms = new MemoryStream())
{//二进制格式化程序BinaryFormatter bf = new BinaryFormatter();//序列化对象 生成二进制字节数组 写入到内存流当中bf.Serialize(ms, obj);//得到对象的二进制字节数组byte[] bytes = ms.GetBuffer();//存储字节File.WriteAllBytes(Application.dataPath + "/Test.bytes", bytes);
}/****************************反序列化(二进制文件)****************************/
//目前没有网络传输 我们还是直接从文件中获取
byte[] bytes = File.ReadAllBytes(Application.dataPath + "/Test.bytes");
//申明内存流对象 一开始就把字节数组传输进去
using (MemoryStream ms = new MemoryStream(bytes))
{//申明一个 2进制格式化程序BinaryFormatter bf = new BinaryFormatter();//反序列化var result = bf.Deserialize(ms) as Student;
}
第二种方法
var filePath = Application.dataPath + "/Student.bytes";
/****************************序列化(二进制文件)****************************/
using (FileStream fs = File.OpenWrite(filePath)){//申明一个二进制格式化类BinaryFormatter bf = new BinaryFormatter();//序列化对象 生成2进制字节数组 写入到内存流当中bf.Serialize(fs, obj);
}/****************************反序列化(二进制文件)****************************/
//通过文件夹流打开指定的2进制数据文件
using (FileStream fs = File.OpenRead(filePath)){//申明一个二进制格式化类BinaryFormatter bf = new BinaryFormatter();//反序列化Student result = bf.Deserialize(fs) as Student;
}
优缺点
优点 | (相比于json和xml方案) 1、安全性较高 2、文件读写时效率较高 3、内存和硬盘占用空间小 |
缺点 | 1、可读性低,不易于人类阅读 |
适用范围
广泛应用于网络通信
XML(不推荐)
不支持序列化字典
//XML序列化
void SerializeToXML<T>(T data, string path) {XmlSerializer serializer = new XmlSerializer(typeof(T));using (StreamWriter stream = new StreamWriter(path)) {serializer.Serialize(stream, data);}
}//XML反序列化
T DeserializeFromXML<T>(string path) {XmlSerializer serializer = new XmlSerializer(typeof(T));using (StreamReader stream = new StreamReader(path)) {return (T)serializer.Deserialize(stream);}
}