Xml数据持久化
Unity XML 数据持久化
1. 最基础的 XML 序列化示例
假设我们要保存角色数据:
public class RoleInfo
{
public int hp;
public int speed;
}
使用 XmlSerializer 序列化:
//保存到xml文件中 data是RoleInfo的对象
public void SavaData(object data,string fileName)
{
//1.得到存储路径
string path = Application.persistentDataPath + "/" + fileName + ".xml";
Debug.Log(path);
//2.存储文件
using(StreamWriter writer = new StreamWriter(path))
{
XmlSerializer sr = new XmlSerializer(data.GetType());
//3.序列化
sr.Serialize(writer, data);
}
}
反序列化:
//方法二:反序列化到对象中
public T LoadData<T>(string fileName)
{
string path = Application.persistentDataPath + "/" + fileName + ".xml";
if (!File.Exists(path))
{
path = Application.streamingAssetsPath + "/" + fileName + ".xml";
if (!File.Exists(path))
{
//如果根本不存在路径 那么直接new一个对象给外面 是默认值
return Activator.CreateInstance<T>();
}
}
using (StreamReader reader = new StreamReader(path))
{
XmlSerializer sr = new XmlSerializer(typeof(T));
return (T)sr.Deserialize(reader);
}
}
2. [XmlAttribute] 与 [XmlElement] 的区别
① [XmlAttribute] → 将文本写入为标签的属性
[XmlAttribute]
public int hp;
[XmlAttribute]
public int speed;
<role hp="10" speed="5" />
② [XmlElement] → 文本InnerText形式(默认的形式)
[XmlElement]
public int hp;
[XmlElement]
public int speed;
<role>
<hp>10</hp>
<speed>5</speed>
</role>
3. 列表 List 的序列化
假设有角色列表:
public class RoleData
{
public List<RoleInfo> roleList = new List<RoleInfo>();
}
public class RoleInfo
{
[XmlAttribute]
public int hp;
[XmlAttribute]
public int speed;
}
序列化后的XML或自己配置的XML:
<RoleData>
<roleList>
<roleInfo hp="4" speed="6"/>
<roleInfo hp="3" speed="7"/>
</roleList>
</RoleData>
4. 通用的 XML 管理器:XmlDataMgr(不支持序列化、反序列字典数据)
using System;
using System.IO;
using System.Xml.Serialization;
using UnityEngine;
public class XmlDataMgr
{
private static XmlDataMgr instance = new XmlDataMgr();
public static XmlDataMgr Instance => instance;
private XmlDataMgr() { }
// 保存
public void SavaData(object data, string fileName)
{
string path = Application.persistentDataPath + "/" + fileName + ".xml";
Debug.Log(path);
using (StreamWriter writer = new StreamWriter(path))
{
XmlSerializer sr = new XmlSerializer(data.GetType());
sr.Serialize(writer, data);
}
}
// 加载(使用 Type)
public object LoadData(Type type, string fileName)
{
string path = Application.persistentDataPath + "/" + fileName + ".xml";
if (!File.Exists(path))
{
path = Application.streamingAssetsPath + "/" + fileName + ".xml";
if (!File.Exists(path))
{
return Activator.CreateInstance(type);
}
}
using (StreamReader reader = new StreamReader(path))
{
XmlSerializer sr = new XmlSerializer(type);
return sr.Deserialize(reader);
}
}
// 加载(泛型)
public T LoadData<T>(string fileName)
{
string path = Application.persistentDataPath + "/" + fileName + ".xml";
if (!File.Exists(path))
{
path = Application.streamingAssetsPath + "/" + fileName + ".xml";
if (!File.Exists(path))
{
return Activator.CreateInstance<T>();
}
}
using (StreamReader reader = new StreamReader(path))
{
XmlSerializer sr = new XmlSerializer(typeof(T));
return (T)sr.Deserialize(reader);
}
}
}
- 自动选择 persistentDataPath 或 streamingAssetsPath
- 文件不存在时返回默认对象(由程序员自己设计的数据默认值决定)
5. 自定义字典 Dictionary<TKey,TValue> 的序列化(重点)
XmlSerializer 默认 无法直接处理 Dictionary,所以我们通过 IXmlSerializable 自定义规则。
自定义字典的规则无需手动调用,XmlSerializer 会自动使用规则,只需要在定义数据类时使用SerializerDictionary而不是Dictionary
保存、加载正常使用XmlDataMgr即可
完整代码:
using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
public class SerializerDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
public XmlSchema GetSchema() => null;
// 反序列化
public void ReadXml(XmlReader reader)
{
XmlSerializer keySer = new XmlSerializer(typeof(TKey));
XmlSerializer valSer = new XmlSerializer(typeof(TValue));
reader.Read(); // 跳过根节点
while (reader.NodeType != XmlNodeType.EndElement)
{
TKey key = (TKey)keySer.Deserialize(reader);
TValue val = (TValue)valSer.Deserialize(reader);
this.Add(key, val);
}
reader.Read(); // 跳过结束节点
}
// 序列化
public void WriteXml(XmlWriter writer)
{
XmlSerializer keySer = new XmlSerializer(typeof(TKey));
XmlSerializer valSer = new XmlSerializer(typeof(TValue));
foreach (var kv in this)
{
keySer.Serialize(writer, kv.Key);
valSer.Serialize(writer, kv.Value);
}
}
}
效果(示例):
<dict>
<int>1</int>
<string>hello</string>
<int>2</int>
<string>world</string>
</dict>
6. 实践示例:角色数据 XML 文件结构
using System.Collections.Generic;
using System.Xml.Serialization;
public class RoleData
{
public List<RoleInfo> roleList = new List<RoleInfo>();
}
public class RoleInfo
{
[XmlAttribute]
public int hp;
[XmlAttribute]
public int speed;
[XmlAttribute]
public int volume;
[XmlAttribute]
public string resName;
[XmlAttribute]
public float scale;
}
配置文件 XML 示例:
<?xml version="1.0" encoding="utf-8"?>
<RoleData>
<roleList>
<roleInfo hp="4" speed="6" volume="5" resName="Airplane/Airplane1" scale="15"/>
<roleInfo hp="3" speed="7" volume="4" resName="Airplane/Airplane2" scale="15"/>
<roleInfo hp="2" speed="8" volume="3" resName="Airplane/Airplane3" scale="15"/>
<roleInfo hp="10" speed="3" volume="10" resName="Airplane/Airplane4" scale="6"/>
<roleInfo hp="6" speed="5" volume="7" resName="Airplane/Airplane5" scale="15"/>
</roleList>
</RoleData>
获取角色数据相关
//单例DataManager中
private RoleData roleData;
public RoleData RoleData => roleData;
//DataManager私有构造函数中初始化角色数据相关
private DataManager()
{
roleData = XmlDataMgr.Load<RoleData>(fileName);
}

浙公网安备 33010602011771号