本博客主要记录PlayerPrefs的使用,比较长
1、什么是数据持久化
数据持久化就是将内存中的数据模型转化为存储模型,以及将存储模型转化为内存中数据模型的通称 简述:将游戏中的数据存储到硬盘,然后可以下次进游戏的时候读取硬盘中的数据到内存。
2、什么是XML
首先XML是可扩展性标记语言,被用来传输和存储数据。
具体语法和规范不再赘述,可自行查找资料。
XML资料
3、将类中属性转化为XML写法
图1
<?xml version="1.0" encoding="UTF-8"?>
<PlayerInfo>
<name>name哥</name>
<atk>10</atk>
<def>5</def>
<moveSpeed>20</moveSpeed>
<roundSpeed>20</roundSpeed>
<weapon>
<id>1</id>
<num>1</num>
</weapon>
<listInt>
<int>1</int>
<int>2</int>
<int>3</int>
</listInt>
<itemList>
<Item id="1" num="10"/>
<Item id="2" num="20"/>
<Item id="3" num="30"/>
<Item id="4" num="40"/>
</itemList>
<itemDic>
<int>1</int>
<Item id="1" num="1"/>
<int>2</int>
<Item id="2" num="1"/>
<int>3</int>
<Item id="3" num="1"/>
</itemDic>
</PlayerInfo>
4、C#读取XML文件的方法
- 1、XmlDocument (把数据加载到内存中,方便读取)
- 2、XmlTextReader (以流形式加载,内存占用更少,但是是单向只读,使用不是特别方便,除非有特殊需求,否则不会使用)
- 3、Linq 待补充
4.1 XmlDocument
//使用XmlDocument类读取是较方便最容易理解和操作的方法
#region 知识点一 读取xml文件信息
XmlDocument xml = new XmlDocument();
//通过XmlDocument读取xml文件 有两个API
//1.直接根据xml字符串内容 来加载xml文件
//存放在Resorces文件夹下的xml文件加载处理
TextAsset asset = Resources.Load<TextAsset>("TestXml");
print(asset.text);
//通过这个方法 就能够翻译字符串为xml对象
xml.LoadXml(asset.text);
//2.是通过xml文件的路径去进行加载
xml.Load(Application.streamingAssetsPath + "/TestXml.xml");
#endregion
#region 知识点二 读取元素和属性信息
//节点信息类
//XmlNode 单个节点信息类
//节点列表信息
//XmlNodeList 多个节点信息类
//获取xml当中的根节点,注意Root是节点的名字而不是其他意思
XmlNode root = xml.SelectSingleNode("Root");
//再通过根节点 去获取下面的子节点
XmlNode nodeName = root.SelectSingleNode("name");
//如果想要获取节点包裹的元素信息 直接 .InnerText
print(nodeName.InnerText);
XmlNode nodeAge = root.SelectSingleNode("age");
print(nodeAge.InnerText);
//对于内部有多组数据的
XmlNode nodeItem = root.SelectSingleNode("Item");
//第一种方式 直接用 中括号获取信息
print(nodeItem.Attributes["id"].Value);
print(nodeItem.Attributes["num"].Value);
//第二种方式
print(nodeItem.Attributes.GetNamedItem("id").Value);
print(nodeItem.Attributes.GetNamedItem("num").Value);
//这里是获取 一个节点下的同名节点的方法
XmlNodeList friendList = root.SelectNodes("Friend");
//遍历方式一:迭代器遍历
//foreach (XmlNode item in friendList)
//{
// print(item.SelectSingleNode("name").InnerText);
// print(item.SelectSingleNode("age").InnerText);
//}
//遍历方式二:通过for循环遍历
//通过XmlNodeList中的 成员变量 Count可以得到 节点数量
for (int i = 0; i < friendList.Count; i++)
{
print(friendList[i].SelectSingleNode("name").InnerText);
print(friendList[i].SelectSingleNode("age").InnerText);
}
#endregion
4.2 XmlDocument总结
//1.读取XML文件
//XmlDocument xml = new XmlDocument();
//读取文本方式1-xml.LoadXml(传入xml文本字符串)
//读取文本方式2-xml.Load(传入路径)
//2.读取元素和属性
//获取单个节点 : XmlNode node = xml.SelectSingleNode(节点名)
//获取多个节点 : XmlNodeList nodeList = xml.SelectNodes(节点名)
//获取节点元素内容:node.InnerText
//获取节点元素属性:
//1.item.Attributes["属性名"].Value
//2.item.Attributes.GetNamedItem("属性名").Value
//通过迭代器遍历或者循环遍历XmlNodeList对象 可以获取到各单个元素节点
4.3 利用XmlDocument将XML转成类对象
参考图1
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using UnityEngine;
public class Item
{
public int id;
public int num;
}
public class PlayerInfo
{
public string name;
public int atk;
public int def;
public float moveSpeed;
public float roundSpeed;
public Item weapon;
public List<int> listInt;
public List<Item> itemList;
public Dictionary<int, Item> itemDic;
public void LoadData(string fileName)
{
//加载XML文件信息
XmlDocument xml = new XmlDocument();
//加载
xml.Load(Application.streamingAssetsPath + "/" + fileName + ".xml");
//从文件中加载出具体的数据
//加载根节点 才能加载后面的内容
XmlNode playerInfo = xml.SelectSingleNode("PlayerInfo");
//通过根节点 去加载具体的信息
this.name = playerInfo.SelectSingleNode("name").InnerText;
this.atk = int.Parse(playerInfo.SelectSingleNode("atk").InnerText);
this.def = int.Parse(playerInfo.SelectSingleNode("def").InnerText);
this.moveSpeed = float.Parse(playerInfo.SelectSingleNode("moveSpeed").InnerText);
this.roundSpeed = float.Parse(playerInfo.SelectSingleNode("roundSpeed").InnerText);
XmlNode weaponNode = playerInfo.SelectSingleNode("weapon");
this.weapon = new Item();
this.weapon.id = int.Parse(weaponNode.SelectSingleNode("id").InnerText);
this.weapon.num = int.Parse(weaponNode.SelectSingleNode("num").InnerText);
XmlNode listIntNode = playerInfo.SelectSingleNode("listInt");
XmlNodeList intList = listIntNode.SelectNodes("int");
this.listInt = new List<int>();
for (int i = 0; i < intList.Count; i++)
{
this.listInt.Add(int.Parse(intList[i].InnerText));
}
XmlNode itemList = playerInfo.SelectSingleNode("itemList");
XmlNodeList items = itemList.SelectNodes("Item");
this.itemList = new List<Item>();
foreach (XmlNode item in items)
{
Item item2 = new Item();
item2.id = int.Parse(item.Attributes["id"].Value);
item2.num = int.Parse(item.Attributes["num"].Value);
this.itemList.Add(item2);
}
XmlNode itemDic = playerInfo.SelectSingleNode("itemDic");
XmlNodeList keyInt = itemDic.SelectNodes("int");
XmlNodeList valueItem = itemDic.SelectNodes("Item");
this.itemDic = new Dictionary<int, Item>();
for (int i = 0; i < keyInt.Count; i++)
{
int key = int.Parse(keyInt[i].InnerText);
Item value = new Item();
value.id = int.Parse(valueItem[i].Attributes["id"].Value);
value.num = int.Parse(valueItem[i].Attributes["num"].Value);
this.itemDic.Add(key, value);
}
}
}
5、存储XML
注意:存储xml文件 在Unity中一定是使用各平台都可读可写可找到的路径
1.Resources 可读 不可写 打包后找不到 ×
2.Application.streamingAssetsPath 可读 PC端可写 找得到 ×
3.Application.dataPath 打包后找不到 ×
4.Application.persistentDataPath 可读可写找得到 √
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using UnityEngine;
public class SaveXml : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
#region 知识点一 决定存储在哪个文件夹下
string path = Application.persistentDataPath + "/PlayerInfo2.xml";
print(Application.persistentDataPath);
#endregion
#region 知识点二 存储xml文件
//关键类 XmlDocument 用于创建节点 存储文件
//关键类 XmlDeclaration 用于添加版本信息
//关键类 XmlElement 节点类
//存储有5步
//1.创建文本对象
XmlDocument xml = new XmlDocument();
//2.添加固定版本信息
//这一句代码 相当于就是创建<?xml version="1.0" encoding="UTF-8"?>这句内容
XmlDeclaration xmlDec = xml.CreateXmlDeclaration("1.0", "UTF-8", "");
//创建完成过后 要添加进入 文本对象中
xml.AppendChild(xmlDec);
//3.添加根节点
XmlElement root = xml.CreateElement("Root");
xml.AppendChild(root);
//4.为根节点添加子节点
//加了一个 name子节点
XmlElement name = xml.CreateElement("name");
name.InnerText = "唐老狮";
root.AppendChild(name);
XmlElement atk = xml.CreateElement("atk");
atk.InnerText = "10";
root.AppendChild(atk);
XmlElement listInt = xml.CreateElement("listInt");
for (int i = 1; i <= 3; i++)
{
XmlElement childNode = xml.CreateElement("int");
childNode.InnerText = i.ToString();
listInt.AppendChild(childNode);
}
root.AppendChild(listInt);
XmlElement itemList = xml.CreateElement("itemList");
for (int i = 1; i <= 3; i++)
{
XmlElement childNode = xml.CreateElement("Item");
//添加属性
childNode.SetAttribute("id", i.ToString());
childNode.SetAttribute("num", (i * 10).ToString());
itemList.AppendChild(childNode);
}
root.AppendChild(itemList);
//5.保存
xml.Save(path);
#endregion
#region 知识点三 修改xml文件
//1.先判断是否存在文件
if( File.Exists(path) )
{
//2.加载后 直接添加节点 移除节点即可
XmlDocument newXml = new XmlDocument();
newXml.Load(path);
//修改就是在原有文件基础上 去移除 或者添加
//移除
XmlNode node;// = newXml.SelectSingleNode("Root").SelectSingleNode("atk");
//这种是一种简便写法 通过/来区分父子关系
node = newXml.SelectSingleNode("Root/atk");
//得到自己的父节点
XmlNode root2 = newXml.SelectSingleNode("Root");
//移除子节点方法
root2.RemoveChild(node);
//添加节点
XmlElement speed = newXml.CreateElement("moveSpeed");
speed.InnerText = "20";
root2.AppendChild(speed);
//改了记得存
newXml.Save(path);
}
#endregion
#region 总结
//1.路径选取
//在运行过程中存储 只能往可写且能找到的文件夹存储
//故 选择了Application.persistentDataPath
//2.存储xml关键类
//XmlDocument 文件
// 创建节点 CreateElement
// 创建固定内容方法 CreateXmlDeclaration
// 添加节点 AppendChild
// 保存 Save
//XmlDeclaration 版本
//XmlElement 元素节点
// 设置属性方法SetAttribute
//3.修改
//RemoveChild移除节点
//可以通过 /的形式 来表示 子节点的子节点
#endregion
}
// Update is called once per frame
void Update()
{
}
}
|