Unity数据持久化设计三 XML

Unity数据持久化设计

Unity数据持久化一 PlayerPrefs
Unity数据持久化二 JSON



前言

1. XML基础概念与Unity集成

1.1 XML简介

XML(可扩展标记语言,Extensible Markup Language),主要是以一种结构化且具有一定描述性的方式组织数据管理,常用于存储与数据传输的标记性语言,被广泛应用于不同系统之间的数据交换,XML的设计目标主要是传输数据不是显示数据。

1.2 XML在Unity中的优势

XML也具有一定的特点优势,具体如下:

特点 描述
易读易懂 数据以文本的形式进行存储,方便与调试和手动修改
结构清晰 层次结构清晰,适合存储于复杂数据关系
跨平台兼容 所有平台都支持XML解析
扩展性强 支持复杂数据结构和自定义格式

相较于JSON存储也有一定的对比性
相同点:
JSON与XML都是纯文本存储,都具有层级结构,都拥有一定的描述性。
不同点:
相较于配置简易型JSON更简单一点,且某些情况下JSON读写更快捷。

1.3 Unity中XML处理配置

在Unity中使用需要进行脚本的命名空间引用,使用的命名空间包含以下内容:

	using System.Xml;  //XML文件处理
	using System.Xml.Serialization;	//XML序列化
	using System.IO; //IO文件操作
	using System.Text; //编码处理

引入相应的命名空间之后进行XML文件的操作编写。

2. XML基础

使用XML需要利用序列化与反序列化进行数据存储转换
序列化与反序列化-百度百科
可以参考以上内容进行学习序列化与反序列化知识。
具体的创建和读取XML可以用一个简单的示例来呈现。

	using UnityEngine;
using System.Xml;
using System.IO;

public class BasicXMLExample : MonoBehaviour
{
   
   
    private string xmlFilePath;
    
    void Start()
    {
   
   
        xmlFilePath = Path.Combine(Application.persistentDataPath, "basic_data.xml");
        
        // 创建示例 XML 数据
        CreateBasicXML();
        
        // 读取并解析 XML 数据
        ReadBasicXML();
    }
    
    /// <summary>
    /// 手动创建 XML 文件 - 基础方法
    /// </summary>
    void CreateBasicXML()
    {
   
   
        try
        {
   
   
            // 创建 XML 写入设置
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;                    // 启用缩进
            settings.IndentChars = "  ";               // 缩进字符
            settings.NewLineChars = "\n";              // 换行符
            settings.Encoding = Encoding.UTF8;         // 使用 UTF-8 编码
            
            // 创建 XmlWriter
            using (XmlWriter writer = XmlWriter.Create(xmlFilePath, settings))
            {
   
   
                writer.WriteStartDocument();           // 开始文档
                writer.WriteStartElement("PlayerData"); // 根元素
                
                // 写入基本玩家信息
                writer.WriteElementString("Name", "张三");
                writer.WriteElementString("Level", "25");
                writer.WriteElementString("Experience", "12500.5");
                writer.WriteElementString("Health", "85");
                
                // 写入物品列表
                writer.WriteStartElement("Inventory");
                WriteInventoryItem(writer, "Sword", "1", "2.5");
                WriteInventoryItem(writer, "HealthPotion", "5", "0.5");
                WriteInventoryItem(writer, "GoldCoin", "150", "0.01");
                writer.WriteEndElement(); // 结束 Inventory
                
                writer.WriteEndElement(); // 结束 PlayerData
                writer.WriteEndDocument(); // 结束文档
            }
            
            Debug.Log($"基础 XML 文件创建成功: {
     
     xmlFilePath}");
        }
        catch (System.Exception e)
        {
   
   
            Debug.LogError($"创建 XML 文件失败: {
     
     e.Message}");
        }
    }
    
    /// <summary>
    /// 写入物品项到 XML
    /// </summary>
    void WriteInventoryItem(XmlWriter writer, string name, string count, string weight)
    {
   
   
        writer.WriteStartElement("Item");
        writer.WriteAttributeString("name", name);
        writer.WriteAttributeString("count", count);
        writer.WriteAttributeString("weight", weight);
        writer.WriteEndElement();
    }
    
    /// <summary>
    /// 读取和解析 XML 文件 - 基础方法
    /// </summary>
    void ReadBasicXML()
    {
   
   
        if (!File.Exists(xmlFilePath))
        {
   
   
            Debug.LogWarning("XML 文件不存在");
            return;
        }
        
        try
        {
   
   
            // 加载 XML 文档
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(xmlFilePath);
            
            // 获取根节点
            XmlNode root = xmlDoc.DocumentElement;
            
            // 读取基本玩家信息
            string playerName = root.SelectSingleNode("Name")?.InnerText ?? "未知";
            int level = int.Parse(root.SelectSingleNode("Level")?.InnerText ?? "1");
            float experience = float.Parse(root.SelectSingleNode("Experience")?.InnerText ?? "0");
            int health = int.Parse(root.SelectSingleNode("Health")?.InnerText ?? "100");
            
            Debug.Log($"玩家信息 - 名称: {
     
     playerName}, 等级: {
     
     level}, 经验: {
     
     experience}, 生命: {
     
     health}");
            
            // 读取物品列表
            XmlNode inventoryNode = root.SelectSingleNode("Inventory");
            if (inventoryNode != null)
            {
   
   
                Debug.Log("物品栏内容:");
                foreach (XmlNode itemNode in inventoryNode.SelectNodes("Item"))
                {
   
   
                    string itemName = itemNode.Attributes["name"]?.Value ?? "未知物品";
                    string itemCount = itemNode.Attributes["count"]?.Value ?? "0";
                    string itemWeight = itemNode.Attributes["weight"]?.Value ?? "0";
                    
                    Debug.Log($"  - {
     
     itemName} x{
     
     itemCount} (重量: {
     
     itemWeight})");
                }
            }
        }
        catch (System.Exception e)
        {
   
   
            Debug.LogError($"读取 XML 文件失败: {
     
     e.Message}");
        }
    }
}

如果需要对自定义类进行XML数据存储那就需要对自定义类进行XML序列化特性加入,如:

	using System.Xml.Serialization;

[System.Serializable]
public class PlayerBasicData
{
   
   
    public string playerName;
    public int level;
    public float experience;
    public int health;
    public bool isPremium;
    
    // XmlSerializer 需要无参构造函数
    public PlayerBasicData() {
   
    }
    
    public PlayerBasicData(string name, int level, float exp, int health, bool premium)
    {
   
   
        this.playerName = name;
        this.level = level;
        this.experience = exp;
        this.health = health;
        this.isPremium = premium;
    }
}

public class XMLSerializerExample : MonoBehaviour
{
   
   
    private string filePath;
    
    void Start()
    {
   
   
        filePath = Path.Combine(Application.persistentDataPath, "player_data.xml");
        
        // 序列化示例
        SerializePlayerData();
        
        // 反序列化示例
        DeserializePlayerData();
    }
    
    /// <summary>
    /// 使用 XmlSerializer 序列化对象到 XML
    /// </summary>
    void SerializePlayerData()
    {
   
   
        try
        {
   
   
            // 创建玩家数据对象
            PlayerBasicData player = new PlayerBasicData("李四", 30, 25000.75f, 95, true);
            
            // 创建 XmlSerializer
            XmlSerializer serializer = new XmlSerializer(typeof(PlayerBasicData));
            
            // 创建写入设置
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.Encoding = Encoding.UTF8;
            
            // 序列化到文件
            using (XmlWriter writer = XmlWriter.Create(filePath, settings))
            {
   
   
                serializer.Serialize(writer, player);
            }
            
            Debug.Log($"玩家数据序列化成功: {
     
     filePath}");
        }
        catch (System.Exception e)
        {
   
   
            Debug.LogError($"序列化失败: {
     
     e.Message}");
        }
    }
    
    /// <summary>
    /// 使用 XmlSerializer 从 XML 反序列化对象
    /// </summary>
    void DeserializePlayerData()
    {
   
   
        if (!File.Exists(filePath))
        {
   
   
            Debug.LogWarning("XML 文件不存在");
            return;
        }
        
        try
        {
   
   
            // 创建 XmlSerializer
            XmlSerializer serializer = new XmlSerializer(typeof(PlayerBasicData));
            
            // 从文件反序列化
            using (FileStream stream = new FileStream(filePath, FileMode.Open))
            {
   
   
                PlayerBasicData loadedPlayer = (PlayerBasicData)serializer.Deserialize(stream);
                
                Debug.Log($"反序列化成功 - 名称: {
     
     loadedPlayer.playerName}, " +
                         $"等级: {
     
     loadedPlayer.level}, 经验: {
     
     loadedPlayer.experience}");
            }
        }
        catch (System.Exception e)
        {
   
   
            Debug.LogError($"反序列化失败: {
     
     e.Message}");
        }
    }
}

加入相应的特性之后就可以对自定义对象进行XML序列化与反序列化操作了。

3. XML序列化封装

3.1 XML数据管理器

为了更好的方便使用XML实现数据的管理,如加密、压缩、版本控制和错误恢复等,可以将XML进行封装成高级的数据管理器,这样能够更有效的提供XML序列化解决方案,示例如下:

	using System;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Text;
using System.Collections.Generic;

/// <summary>
/// 高级 XML 数据管理器 - 提供完整的 XML 序列化解决方案
/// 支持加密、压缩、版本控制和错误恢复
/// </summary>
public static class AdvancedXMLDataManager
{
   
   
    // 默认编码
    private static Encoding defaultEncoding = Encoding.UTF8;
    
    /// <summary>
    /// XML 序列化设置
    /// </summary>
    [System.Serializable]
    public class XMLSerializeSettings
    {
   
   
        public bool formatOutput = true;           // 是否格式化输出
        public bool includeNamespace = false;      // 是否包含命名空间
        public Encoding encoding = null;           // 编码格式
        public bool enableEncryption = false;      // 启用加密
        public string encryptionKey = "";          // 加密密钥
        
        public XMLSerializeSettings()
        {
   
   
            encoding = Encoding.UTF8;
        }
    }
    
    #region 基础序列化方法
    
    /// <summary>
    /// 序列化对象到 XML 文件
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="obj">要序列化的对象</param>
    /// <param name="filePath">文件路径</param>
    /// <param name="settings">序列化设置</param>
    /// <returns>是否成功</returns>
    public static bool SerializeToFile<T>(T obj, string filePath, XMLSerializeSettings settings = null)
    {
   
   
        if (obj == null)
        {
   
   
            Debug.LogError("序列化失败: 对象为 null");
            return false;
        }
        
        try
        {
   
   
            settings = settings ?? new XMLSerializeSettings();
            
            // 确保目录存在
            string directory = Path.GetDirectoryName(filePath);
            if (!Directory.Exists(directory))
            {
   
   
                Directory.CreateDirectory(directory);
            }
            
            // 创建 XmlSerializer
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            
            // 配置 XmlWriter 设置
            XmlWriterSettings writerSettings = new XmlWriterSettings();
            writerSettings.Indent = settings.formatOutput;
            writerSettings.IndentChars = "  ";
            writerSettings.Encoding = settings.encoding ?? defaultEncoding;
            writerSettings.NewLineChars = "\n";
            writerSettings.OmitXmlDeclaration = false;
            
            // 序列化到文件
            using (XmlWriter writer = XmlWriter.Create(filePath, writerSettings))
            {
   
   
                // 移除默认命名空间
                XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
                if (!settings.includeNamespace)
                {
   
   
                    namespaces.Add("", "");
                }
                
                serializer.Serialize(writer, obj, namespaces);
            }
            
            Debug.Log($"XML 序列化成功: {
     
     filePath}");
            return true;
        }
        catch (Exception e)
        {
   
   
            Debug.LogError($"XML 序列化失败: {
     
     e.Message}\n{
     
     e.StackTrace}");
            return false;
        }
    }
    
    /// <summary>
    /// 从 XML 文件反序列化对象
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="filePath">文件路径</param>
    /// <returns>反序列化的对象</returns>
    public static T DeserializeFromFile<T>(string filePath) where T : class
    {
   
   
        if (!File.Exists(filePath))
        {
   
   
            Debug.LogWarning($"XML 文件不存在: {
     
     filePath}");
            return default(T);
        }
        
        try
        {
   
   
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            
            using (FileStream stream = new FileStream(filePath, FileMode.Open))
            {
   
   
                T obj = (T)serializer.Deserialize(stream);
                Debug.Log($"XML 反序列化成功: {
     
     filePath}");
                return obj;
            }
        }
        catch (Exception e)
        {
   
   
            Debug.LogError($"XML 反序列化失败: {
     
     e.Message}\n{
     
     e.StackTrace}");
            return default(T);
        }
    }
    
    /// <summary>
    /// 序列化对象到 XML 字符串
    /// </summary>
    public 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值