一、PlayerPrefs:数据持久化方案
常见的方法如下:
// PlayerPrefs读取
PlayerPrefs.GetInt("123asd"); // 如果我们之前没有过这个键,那么返回默认值就是0
PlayerPrefs.GetFloat("asd"); // 如果我们之前没有过这个键,那么返回默认值就是0
PlayerPrefs.GetString("123"); // 如果我们之前没有过这个键,那么返回默认值就是Null
// 我们是可以修改方法返回的默认值的,另外两个API同理
// 我们通常可以使用在玩家基础数据初始化
PlayerPrefs.GetInt("zzz", 100); // 如果我们之前没有过这个键,那么返回默认值就是100
// PlayerPrefs判断数据是否存在
PlayerPrefs.HasKey("XXX");
// PlayerPrefs删除数据
PlayerPrefs.DeleteKey("XXX"); // 删除指定键值对的数据
PlayerPrefs.DeleteAll(); // 删除所有键值对的数据
参考功能及代码:
通过单选框是否被勾选上,从而来决定是否播放背景音乐,代码如下:
using UnityEngine.UI;
public class MusicManager : MonoBehaviour
{
// 音乐开关单选框 和 播放背景音乐的 musicAudio 组件
public Toggle musicToggle;
public AudioSource musicAudio;
private void Awake()
{
if (PlayerPrefs.HasKey("MusicOn"))
{
if (PlayerPrefs.GetInt("MusicOn") == 1)
{
// 当 单选框 勾选时, 激活 musicAudio 组件
musicToggle.isOn = true;
musicAudio.enabled = true;
}
else
{
// 当 单选框 未勾选时, 让 musicAudio 组件失活
musicToggle.isOn = false;
musicAudio.enabled = false;
}
}else
{
musicToggle.isOn = true;
}
}
private void Update()
{
MusicSwitch();
}
private void MusicSwitch() {
// 通过单选框是否被勾选上,从而来决定是否播放背景音乐
if (musicToggle.isOn == false)
{
musicAudio.enabled = false;
// 保存音乐开关的状态, 0代表暂停 1 代表播放
PlayerPrefs.SetInt("MusicOn",0);
}
else {
musicAudio.enabled = true;
PlayerPrefs.SetInt("MusicOn", 1);
}
PlayerPrefs.Save();
}
}
二、二进制存储(字节流存储)
序列化:新建或打开一个二进制文件,通过二进制格式器将对象写入该二进制文件。
反序列化:打开待反序列化的二进制文件,通过二进制格式器将文件解析成对象。
参考代码如下:
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
// 这两个命名空间需添加
// 二进制方法:存档和读档
private void SaveByBin() {
// 序列化过程 (将Save 对象转换为字节流)
// 创建Save 对象 并 保存当前游戏状态
Save save = CreateSaveGO();
// 创建一个二进制格式化程序
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("存档文件不存在!");
}
}
三、json存储
JSON序列化:对象 ——> JSON
JSON反序列化:JSON ——> 对象
参考代码如下:
using LitJson;
// 此命名空间需添加
// Json: 存档和读档
private void SaveByJson()
{
Save save = CreateSaveGO();
string filePath = Application.dataPath + "/StreamingFile" + "/byJson.txt";
// 利用 JsonMapper 将save 对象转换Wie Json 格式的字符串
string saceJsonStr = JsonMapper.ToJson(save);
// 将这个字符串写入到文件中
// 创建一个StreamWriter,并将字符串写入文件中
StreamWriter sw = new StreamWriter(filePath);
sw.Write(saceJsonStr);
// 关闭 StreamWrite
sw.Close();
UIManager._Instance.ShowMessage("保存成功!");
}
private void LoadByJson() {
string filePath = Application.dataPath + "/StreamingFile" + "/byJson.txt";
if (File.Exists(filePath))
{
// 创建一个 StreamReader, 用来读取流
StreamReader sr = new StreamReader(filePath);
// 将读取到的流赋值给 jsonStr
string jsonStr = sr.ReadToEnd();
// 关闭
sr.Close();
// 将字符串jsonStr 转换为Save 对象
Save save = JsonMapper.ToObject(jsonStr);
SetGame(save);
UIManager._Instance.ShowMessage(" ");
}
else {
UIManager._Instance.ShowMessage(" 存档文件不存在!");
}
}
注:需先导入该文件再添加(using LitJson;)命名空间,LitJson文件存于百度网盘链接:https://pan.baidu.com/s/1Wor_lltGnGbbBmD2T0Dtqg
提取码:wdrf
四、XML存储
扩展标记语言,用于标记电子文件使其具有结构性的标记语言。 可以用来标记数据、定义数据类型。 序列化与反序列化的方式与二进制方法十分类似。
参考代码如下:
using System.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.livingTargetPointions.Count;i++) {
target = xmlDoc.CreateElement("target");
targetPosition = xmlDoc.CreateElement("targetPosition");
// 设置 InnerText 值
targetPosition.InnerText = save.livingTargetPointions[i].ToString();
monsterType = xmlDoc.CreateElement("monsterType");
monsterType.InnerText = save.livingMonsterTypes[i].ToString();
// 把节点一层层的添加至 XMLDoc 中,请仔细看他们之间的先后顺序,这将是生成XML 文件的顺序
// 设置节点间的层级关系 root ---- target ---- (targetPosition,monsterType)
target.AppendChild(targetPosition);
target.AppendChild(monsterType);
root.AppendChild(target);
}
// 设置射击数和分数节点 并设置层级关系 xmlDoc---- root----(
// target---- (targetPosition,monsterType), 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("保存成功!");
}
}
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.livingTargetPointions.Add(targetPositionIndex);
XmlNode monsterType = target.ChildNodes[1];
int monsterTypeIndex = int.Parse(monsterType.InnerText);
save.livingMonsterTypes.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("存档文件不存在");
}
}
后三种方法优缺点对比:
二进制方法:简单,但可读性差。
XML:可读性强,但是文件庞大,冗余信息多。
JSON:数据格式比较简单,易于读写,但是不直观,可读性比XML差。
参考链接:Unity中使用的四种存档和读档方式_Wisdom_off的博客-CSDN博客_unity 存档