11.20闲话-存档
存档
使用没有存档的软件,就像吃饭不给容器一般。
故存档必然是极为重要的。
下面介绍Unity的几种存档方式。
Part.1——PlayerPrefs
应该是最简单的存档方式。
但局限性也是显然的,只能存储int, float, string
三种类型,就像在文件中存储了三个map <string, int / float / string>
。
PlayerPrefs.SetInt("田所浩二", 114514); // 存
PlayerPrefs.SetString("涛哥", "原神");
string players_id = PlayerPrefs.GetString("涛哥"); // 读
Part.2——存储数据序列化
分为三种:二进制方法、XML方法、JSON方法,各有千秋。
大体就是
序列化 对象 -> 字节流
反序列化 字节流 -> 对象
先创建一个Save类,用于记录需要保存的东西
public class Save
{
public List <string> HZOI_name = new List <string>();
public int id;
}
1. 二进制方式
使用二进制文件进行序列化与反序列化
private void Save_By_Bin()
{
Save save = Create_Save();
BinaryFormatter bf = new BinaryFormatter(); // 创建二进制格式化进程
FileStream fileStream = File.Create(Application.dataPath + "/StreamingFile" + "/byBin.txt"); // 创建文件流
bf.Serialize(fileStream, save);
fileStream.Close(); // 关闭
if (File.Exists(Application.dataPath + "/StreamingFile" + "/byBin.txt"))
{
Debug.Log("保存成功");
}
}
private void Load_By_Bin()
{
if(File.Exists(Application.dataPath + "/StreamingFile" + "/byBin.txt"))
{
BinaryFormatter bf = new BinaryFormatter(); // 创建二进制格式化进程
FileStream fileStream = File.Open(Application.dataPath + "/StreamingFile" + "/byBin.txt", FileMode.Open());
Save save = (Save)bf.Deserialize(fileStream);
fileStream.Close();
Set_Game(save);
Debug.Log("成功");
}
else
{
Debug.Log("What are you doing?");
}
}
2. JSON方法
使用JSON进行序列化与反序列化
//JSON:存档和读档
private void SaveByJson()
{
Save save = Create_Save();
string filePath = Application.dataPath + "/StreamingFile" + "/byJson.json";
//利用JsonMapper将save对象转换为Json格式的字符串
string saveJsonStr = JsonMapper.ToJson(save);
//将这个字符串写入到文件中
//创建一个StreamWriter,并将字符串写入文件中
StreamWriter sw = new StreamWriter(filePath);
sw.Write(saveJsonStr);
sw.Close();
if (File.Exists(Application.dataPath + "/StreamingFile" + "/byBin.txt"))
{
Debug.Log("保存成功");
}
}
private void LoadByJson()
{
string filePath = Application.dataPath + "/StreamingFile" + "/byJson.json";
if(File.Exists(filePath))
{
//创建一个StreamReader,用来读取流
StreamReader sr = new StreamReader(filePath);
//将读取到的流赋值给jsonStr
string jsonStr = sr.ReadToEnd();
//关闭
sr.Close();
//将字符串jsonStr转换为Save对象
Save save = JsonMapper.ToObject<Save>(jsonStr);
SetGame(save);//将保存的信息类初始游戏
Debug.Log("成功");
}
else
{
Debug.Log("What are you doing?");
}
}
XML方法
//XML:存档和读档--要根据XML文件的结点结构进行操作
private void SaveByXml()
{
Save save = CreateSaveGO();
//创建XML文件的存储路径
string filePath = Application.dataPath + "/StreamingFile" + "/byXML.txt";
//创建XML文档
XmlDocument xmlDoc = new XmlDocument();
//创建根节点,即最上层节点
XmlElement root = xmlDoc.CreateElement("save");
//设置根节点中的值
root.SetAttribute("name", "saveFile1");
//创建XmlElement
XmlElement target;
XmlElement targetPosition;
XmlElement monsterType;
//遍历save中存储的数据,将数据转换成XML格式
for(int i = 0; i < save.livingTargetPositions.Count; i++)
{
target = xmlDoc.CreateElement("target");
targetPosition = xmlDoc.CreateElement("targetPosition");
//设置InnerText值
targetPosition.InnerText = save.livingTargetPositions[i].ToString();
monsterType = xmlDoc.CreateElement("monsterType");
monsterType.InnerText = save.livingMonsterTypes[i].ToString();
//设置节点间的层级关系 root -- target -- (targetPosition, monsterType)
target.AppendChild(targetPosition);
target.AppendChild(monsterType);
root.AppendChild(target);
}
//设置射击数和分数节点并设置层级关系 xmlDoc -- root --(target-- (targetPosition, monsterType), id, score)
XmlElement id = xmlDoc.CreateElement("id");
id.InnerText = save.id.ToString();
root.AppendChild(id);
xmlDoc.AppendChild(root);
xmlDoc.Save(filePath);
if (File.Exists(Application.dataPath + "/StreamingFile" + "/byBin.txt"))
{
Debug.Log("保存成功");
}
}
private void LoadByXml()
{
string filePath = Application.dataPath + "/StreamingFile" + "/byXML.txt";
if(File.Exists(filePath))
{
Save save = new Save();
//加载XML文档
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(filePath);
//通过节点名称来获取元素,结果为XmlNodeList类型
XmlNodeList targets = xmlDoc.GetElementsByTagName("target");
//遍历所有的target节点,并获得子节点和子节点的InnerText
if(targets.Count != 0)
{
foreach(XmlNode target in targets)
{
XmlNode targetPosition = target.ChildNodes[0];
int targetPositionIndex = int.Parse(targetPosition.InnerText);
//把得到的值存储到save中
save.livingTargetPositions.Add(targetPositionIndex);
XmlNode monsterType = target.ChildNodes[1];
int monsterTypeIndex = int.Parse(monsterType.InnerText);
save.livingMonsterTypes.Add(monsterTypeIndex);
}
}
XmlNodeList id = xmlDoc.GetElementsByTagName("id");
int shootNumCount = int.Parse(id[0].InnerText);
save.id = shootNumCount;
SetGame(save);//将保存的信息类初始游戏
//TODO: 提示存档不存在或为空,读取成功
Debug.Log("成功");
}
else
{
Debug.Log("What are you doing?");
}
}
Part.3 总结
二进制方法:简单简洁,但可读性极差
JSON方法:可读性好,感觉比较符合人类直觉
XML:冗长,可读性好(?没感觉可读性太好,可能是我太蒻了呜呜呜)