Unity数据的存储——XML(二)

本文介绍了一个游戏存档系统的实现方式,使用Unity进行开发,并通过XML序列化存储游戏数据。系统包括游戏信息存储类GameData,存档管理类GameDataManager,以及具体的存档数据类如PlayerData等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DataBases : 信息基类,存储欲存档的信息。对于各种存档信息可以由此派生。派生类一般不含方法。

DataItems : 信息项基类,操作信息类。为Manager提供所有DataBse。

GameData : 游戏信息,所有需要存档的DataBase都需要存储在改类List中。

GameDataManager : 游戏存档类,提供Save()和Load()接口

实质就是将该类的gamedata对象序列化保存。

XmlSave : Xml序列化类。

PlayerData : 继承DataBase,包含Player需要存档的属性,即坐标,旋转,大小。

PlayerDataItem :继承DataItem, 主要负责存档时将属性放入PlayerData,读档时利用PlayerData对Player设置属性。

TimeData : 继承DataBase,存储当前消耗时间信息。

TimeDataItem : 继承DataItem,主要负责存档时将属性放入TimeData,读档时利用TimeData对显示时间设置。

wasd控制角色前后左右移动,Q存档,E读档

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestDatas : MonoBehaviour {

	void Start () {
        //加载XML数据,加载场景
        SceneRead.LoadSceneXML();
	}
	
	void Update () {
        if (Input.GetKeyDown(KeyCode.Q))
        {
            Debug.Log("存档");
            GameDataManagers._instance.Save();
        }
        if (Input.GetKeyDown(KeyCode.E))
        {
            Debug.Log("读档");
            GameDataManagers._instance.Load();
            List<DataBases> datas = GameDataManagers._instance.cloneData.datas;
            for (int i = 0; i < datas.Count; i++)
            {
                GameObject go = GameObject.Find(datas[i].objName);
                go.GetComponent<DataItems>().Load(datas[i]);
            }
        }
	}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//GameDatas,储存数据的类,把需要储存的诗句定义在GameDatas之内
public class GameDatas  {

    //密钥,用于防止拷贝存档
    public string key;

    //下面是添加需要存储的内容
    public List<DataBases> datas = new List<DataBases>();
    public void Registe(DataBases data)
    {
        datas.Add(data);
    }

}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Xml;

public class GameDataManagers : MonoBehaviour {

    public static GameDataManagers _instance;

    //存档文件的路径和名称
    private string dataFileName = "test/TestGame/TestSave1.data";
    private XmlSaver xs = new XmlSaver();

    public List<DataItems> items;
    public GameDatas gameData;
    public GameDatas cloneData;

    private void Awake()
    {
        gameData = new GameDatas();
        cloneData = new GameDatas();
        _instance = this;
        //设定密钥,根据具体平台设定
        gameData.key = SystemInfo.deviceUniqueIdentifier;
    }

    //存档时调用的函数
    public void Save()
    {
        string gameDataFile = GetDataPath() + "/" + dataFileName;
        for (int i = 0; i < items.Count; i++)
        {
            items[i].Save();
        }
        string dataString = xs.SerializeObject(gameData, typeof(GameDatas));
        xs.CreateXML(gameDataFile, dataString);
    }

    //读档时调用的函数
    public void Load()
    {
        string gameDataFile = GetDataPath() + "/" + dataFileName;
        if (xs.hasFile(gameDataFile))
        {
            string dataString = xs.LoadXML(gameDataFile);
            GameDatas gameDataFromXML = xs.DeserializeObject(dataString, typeof(GameDatas)) as GameDatas;

            //是合法存档
            if (gameDataFromXML.key==gameData.key)
            {
                cloneData = gameDataFromXML;
            }
            //是非法拷贝存档
            else
            {
                //留空:游戏启动后数据清零,存档后作弊档被自动覆盖
            }
        }
        else
        {
            if (gameData!=null)
            {
                Save();
            }
        }
    }

    //获取路径
    private static string GetDataPath()
    {
        return Application.dataPath;
    }

    public void Registe(DataItems item)
    {
        items.Add(item);
    }
}
using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;
using UnityEngine;

//在这里添加你的所有需要序列化的信息类
[XmlInclude(typeof(PlayerDatas))]
[XmlInclude(typeof(TimeDatas))]
[XmlInclude(typeof(CubeDatas))]

public class DataBases
{
    public string objName;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class DataItems : MonoBehaviour {

    public DataBases item;

    public virtual void Start()
    {
        item.objName = this.gameObject.name;
        GameDataManagers._instance.gameData.Registe(item);
        GameDataManagers._instance.Registe(this);
    }

    public abstract void Save();

    public abstract void Load(DataBases data);
}
using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour {

    public float walkSpeed;
    public float rotaSpeed;

    private Rigidbody rigid;
    private Animation anim;
    void Awake()
    {
        rigid = GetComponent<Rigidbody>();
        anim = GetComponent<Animation>();
    }
	void Update () {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");

        Quaternion rota = Quaternion.LookRotation(transform.forward * (v + 1.5f) + transform.right * h);
        transform.rotation = Quaternion.Slerp(transform.rotation, rota, rotaSpeed * Time.deltaTime);

        transform.position = Vector3.Lerp(transform.position, transform.forward * walkSpeed * v * Time.deltaTime + transform.position, 50 * Time.deltaTime);

        if(Mathf.Abs(v) > 0.3f)
        {
            anim.CrossFade("Run");
        }
        else
        {
            anim.Stop();
        }

	}
}
using UnityEngine;
using System.Collections;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using System;
public class XmlSaver
{
    //内容加密
    public string Encrypt(string toE)
    {
        //加密和解密采用相同的key,具体自己填,但是必须为32位//
        byte[] keyArray = UTF8Encoding.UTF8.GetBytes("12348578902223367877723456789012");
        RijndaelManaged rDel = new RijndaelManaged();
        rDel.Key = keyArray;
        rDel.Mode = CipherMode.ECB;
        rDel.Padding = PaddingMode.PKCS7;
        ICryptoTransform cTransform = rDel.CreateEncryptor();

        byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toE);
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

        return Convert.ToBase64String(resultArray, 0, resultArray.Length);
    }

    //内容解密
    public string Decrypt(string toD)
    {
        //加密和解密采用相同的key,具体值自己填,但是必须为32位//
        byte[] keyArray = UTF8Encoding.UTF8.GetBytes("12348578902223367877723456789012");

        RijndaelManaged rDel = new RijndaelManaged();
        rDel.Key = keyArray;
        rDel.Mode = CipherMode.ECB;
        rDel.Padding = PaddingMode.PKCS7;
        ICryptoTransform cTransform = rDel.CreateDecryptor();

        byte[] toEncryptArray = Convert.FromBase64String(toD);
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

        return UTF8Encoding.UTF8.GetString(resultArray);
    }

    public string SerializeObject(object pObject, System.Type ty)
    {
        string XmlizedString = null;
        MemoryStream memoryStream = new MemoryStream();
        XmlSerializer xs = new XmlSerializer(ty);
        XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

        xs.Serialize(xmlTextWriter, pObject);
        memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
        
        XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
        return XmlizedString;
    }

    public object DeserializeObject(string pXmlizedString, System.Type ty)
    {
        XmlSerializer xs = new XmlSerializer(ty);
        MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(pXmlizedString));
        XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
        return xs.Deserialize(memoryStream);
    }

    //创建XML文件
    public void CreateXML(string fileName, string thisData)
    {
        string xxx = Encrypt(thisData);
        StreamWriter writer;
        writer = File.CreateText(fileName);
        writer.Write(xxx);
        writer.Close();
    }

    //读取XML文件
    public string LoadXML(string fileName)
    {
        StreamReader sReader = File.OpenText(fileName);
        string dataString = sReader.ReadToEnd();
        sReader.Close();
        string xxx = Decrypt(dataString);
        return xxx;
    }

    //判断是否存在文件
    public bool hasFile(String fileName)
    {
        return File.Exists(fileName);
    }
    public string UTF8ByteArrayToString(byte[] characters)
    {
        UTF8Encoding encoding = new UTF8Encoding();
        string constructedString = encoding.GetString(characters);
        return (constructedString);
    }

    public byte[] StringToUTF8ByteArray(String pXmlString)
    {
        UTF8Encoding encoding = new UTF8Encoding();
        byte[] byteArray = encoding.GetBytes(pXmlString);
        return byteArray;
    }
}
### Unity 中的数据存储方法 #### PlayerPrefs 存储 Unity 提供了一种简单的键值对持久化存储解决方案——`PlayerPrefs`。这种机制适合用于保存少量数据,比如玩家设置或者游戏进度等简单信息[^1]。 ```csharp // 设置偏好参数 PlayerPrefs.SetInt("HighScore", score); PlayerPrefs.Save(); // 获取偏好参数 int highscore = PlayerPrefs.GetInt("HighScore"); ``` 尽管 `PlayerPrefs` 使用方便,但它并不安全也不适用于大量复杂结构化的数据存储需求。 #### 文件系统操作 通过访问设备本地文件系统来存取更大规模或更复杂的资料成为另一种常见做法。这可能涉及到创建、写入以及读取不同类型的文档,例如纯文本文件(.txt),JavaScript 对象表示法(JSON) 或可扩展标记语言(XML)[^2]。 对于文本文件的操作通常借助于 C# 的标准库函数完成: ```csharp System.IO.File.WriteAllText(path, content); // 写入整个文件的内容 string textFromFile = System.IO.File.ReadAllText(path); // 一次性读取全部内容到字符串变量中 ``` 当涉及网络资源获取时,则会用到专门设计用来处理HTTP请求响应交互过程中的类如 `WWW` 和更新版本的 `UnityWebRequest` API 来简化异步加载远程资产的工作流程并能更好地兼容现代Web服务特性。 ```csharp using UnityEngine.Networking; IEnumerator GetBinaryData(string url) { using (UnityWebRequest www = UnityWebRequest.Get(url)) { yield return www.SendWebRequest(); if(www.result != UnityWebRequest.Result.Success) Debug.LogError(www.error); else { byte[] results = www.downloadHandler.data; // Process binary data here... } } } ``` 上述API不仅限于下载图片音频视频等内容还可以直接解析来自服务器端返回来的JSON/XML格式的消息体从而实现客户端和服务端之间的高效通信。 综上所述,在选择合适的数据储存方案前应当充分考虑应用的具体场景因素包括但不限于性能开销大小安全性要求等因素再做决定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值