一:Unity本地持久化类Playerprefs
1、PlayerPrefs是什么?
PlayerPrefs是Unity3d提供了一个用于数据本地持久化保存与读取的类。工作原理十分简单,就是以key-value的形式将数据保存在本地,然后在代码中可以写入、读取、更新数据。
2、PlayerPrefs有什么用?
可用于存储一些非关键性的数据,尤其在没有服务器的单机游戏中,游戏存档、分数排名等都需要用到数据存储,可以使用PlayerPrefs轻松实现数据存储。
3、PlayerPrefs如何用?
3.1:存储数据
//存储整型数据
PlayerPrefs.SetInt("intKey",999);
//存储浮点型数据
PlayerPrefs.SetFloat("floatKey",1.11f);
//存储字符串数据
PlayerPrefs.SetString("strKey","I am Plane");
3.2:获取数据
//取出key为"intKey"的整型数据
int intVal = PlayerPrefs.GetInt("intKey");
//取出key为"floatKey"的浮点型数据
float floatVal = PlayerPrefs.GetFloat("floatKey");
//获取key为"strKey"的字符串数据
string strVal = PlayerPrefs.GetString("strKey");
3.3:删除与查找数据
//删除所有存储数据
PlayerPrefs.DeleteAll();
//删除key为"score"的数据
PlayerPrefs.DeleteKey("score");
//查找是否存在key为"score"的数据
bool exist = PlayerPrefs.HasKey("score");
3.4: 注意事项:数据以键值对的形式存储,可以看做一个字典。
数据通过键名来读取,当值不存在时,返回默认值。
二:Unity中使用的三种存档方式
Serialization(序列化),可以用来将对象转化为字节流。
Deserialization(反序列化),可以用来将字节流转换为对象。
常见的数据序列化方法:二进制方法,XML方法,JSON方法。
[System.Serializable]
public class Save {
public List<int> livingTargetPositoins = new List<int>();
public List<int> livintMonsterTypes = new List<int>();
public int shootNum = 0;
public int score = 0;
}
/// <summary>
/// 创建Save对象 并存储当前游戏状态信息
/// </summary>
/// <returns></returns>
private Save CreateSaveGo()
{
Save save = new Save();
foreach(GameObject targetGO in targetGOs)//遍历所有的target
{
//如果其中有处于激活状态的怪物 就把该target的位置信息和激活状态的怪物类型添加到LIst中
TargetManager targetManager = targetGO.GetComponent<TargetManager>();
if (targetManager.activeMonster != null)
{
save.livingTargetPositoins.Add(targetManager.targetPosition);
int type = targetManager.activeMonster.GetComponent<MonsterManager>().monsterType;
save.livintMonsterTypes.Add(type);
}
}
//吧shootNum和score保存在save中
save.shootNum = UiManager._instance.shootNum;
save.score = UiManager._instance.score;
return save;
}
private void SetGame(Save save)
{
//先将所有的target里面的怪物清空,并重置所有的计时
foreach(GameObject targetGO in targetGOs)
{
targetGO.GetComponent<TargetManager>().UpdateMonsters();
}
//通过反序列化得到的Save对象中存储的信息,激活指定的怪物
for(int i = 0; i < save.livingTargetPositoins.Count; i++)
{
int position = save.livingTargetPositoins[i];
int type = save.livintMonsterTypes[i];
targetGOs[position].GetComponent<TargetManager>().ActivateMonsterByType(type);
}
//更新UI显示
UiManager._instance.shootNum = save.shootNum;
UiManager._instance.score = save.score;
//调整为未暂停的状态
UnPause();
}
(1):二进制方法
序列化:新建或打开一个二进制文件,通过二进制格式器将对象写入该二进制文件。
反序列化:打开待反序列化的二进制文件,通过二进制格式器将文件解析成对象。
二进制存储数据
private void SaveByBin()
{
//创建save对象 并保存当前游戏状态
Save save = CreateSaveGo();//序列化过程 (将save对象转化为字节流)
BinaryFormatter bf = new BinaryFormatter();//创建一个二进制格式化程序
//创建一个文件流
FileStream fileStream = File.Create(Application.dataPath + "/StreamingFile" + "/byBin.txt");
//用二进制格式化程序的序列化方法来序列化Save对象,参数:创建的文件流和需要序列化的对象
bf.Serialize(fileStream, save);
fileStream.Close();//关闭流
if (File.Exists(Application.dataPath + "/StreamingFile" + "/byBin.txt"))
{
UiManager._instance.ShowMessage("保存成功");
}
}
二进制读取数据
private void LoadByBin()
{
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 = (Save)bf.Deserialize(fileStream);
//关闭文件流
fileStream.Close();
SetGame(save);
UiManager._instance.ShowMessage("");
}
else
{
UiManager._instance.ShowMessage("文档文件不存在");
}
}
(2):JSON方法
JSON:是一种语言无关的发送和接收数据的常用格式。可以使用它来跨平台的传输数据。
JSON序列化:对象 ==> JSON
JSON反序列化:JSON ==> 对象
JSON生成文件格式:
{“livingTargetPositoins”:[0,1,3,4,5,6,7],“livintMonsterTypes”:[3,2,0,3,0,2,2],“shootNum”:14,“score”:14}
JSON存储数据
private void SaveByJson()
{
Save save = CreateSaveGo();
string filePath = Application.dataPath + "/StreamingFile" + "/byJson.json";
//利用JsonMapper将save对象转换为Json格式的字符串
string saveJsonStr = JsonMapper.ToJson(save);
//将这个字符串写入到文件中
//创建一个StreamWriter,并将字符串写入文件中
StreamWriter sw = new StreamWriter(filePath);
sw.Write(saveJsonStr);
//关闭StreamWriter
sw.Close();
UiManager._instance.ShowMessage("保存成功");
}
JSON读取数据
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);
UiManager._instance.ShowMessage("");
}
else
{
UiManager._instance.ShowMessage("存档文件不存在");
}
}
(3):XML方法
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.livingTargetPositoins.Count; i++)
{
target = xmlDoc.CreateElement("target");
targetPosition = xmlDoc.CreateElement("targetPosition");
//设置InnerText值
targetPosition.InnerText = save.livingTargetPositoins[i].ToString();
monsterType = xmlDoc.CreateElement("monsterType");
monsterType.InnerText = save.livintMonsterTypes[i].ToString();
//设置节点间的层级关系 root --targer --(targetPosition,monsterType)
target.AppendChild(targetPosition);
target.AppendChild(monsterType);
root.AppendChild(target);
}
//设置射击数和分数节点并设置层级关系 xmlDoc--root--(target,shootNum,score)
XmlElement shootNum = xmlDoc.CreateElement("shootNum");
shootNum.InnerText = save.shootNum.ToString();
root.AppendChild(shootNum);
XmlElement score = xmlDoc.CreateElement("score");
score.InnerText = save.score.ToString();
root.AppendChild(score);
xmlDoc.AppendChild(root);
xmlDoc.Save(filePath);
if(File.Exists(Application.dataPath + "/StreamingFile" + "/byXML.txt"))
{
UiManager._instance.ShowMessage("保存成功");
}
}
XML读取数据
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.livingTargetPositoins.Add(targetPositionIndex);
XmlNode monsterType = target.ChildNodes[1];
int monsterTypeIndex = int.Parse(monsterType.InnerText);
save.livintMonsterTypes.Add(monsterTypeIndex);
}
}
//得到存储的射击数和分数
XmlNodeList shootNum = xmlDoc.GetElementsByTagName("shootNum");
int shootNumCount = int.Parse(shootNum[0].InnerText);
save.shootNum = shootNumCount;
XmlNodeList score = xmlDoc.GetElementsByTagName("score");
int scoreCount = int.Parse(score[0].InnerText);
save.score = scoreCount;
SetGame(save);
UiManager._instance.ShowMessage("");
}
else
{
UiManager._instance.ShowMessage("存档文件不存在");
}
}