当前位置: 首页 > news >正文

【Unity笔记04】数据持久化

🌟 方案核心思想

遵循以下设计原则:

  1. 数据安全第一:绝不使用明文存储,采用AES加密算法保护数据。
  2. 性能优化:使用异步I/O操作,避免阻塞主线程导致游戏卡顿。
  3. 结构清晰:模块化设计,职责分离,便于维护和扩展。
  4. 易于集成:提供单例入口,全局访问方便。

🧱 模块架构设计

整个数据持久化系统由四个核心模块组成:

PlayerData.cs

数据模型,定义可序列化的玩家数据结构

EncryptionUtility.cs

加密工具类,负责数据的加密与解密

AsyncFileUtility.cs

异步文件操作工具,封装读写逻辑

DataManager.cs

核心管理器,统一调度数据加载与保存

1️⃣ 玩家数据模型:PlayerData.cs

using System;
using System.Collections.Generic;
using UnityEngine;[Serializable]
public class PlayerData
{public string playerName;public int level;public long gold;public List<string> inventoryItems; // 背包物品列表public Dictionary<string, int> equippedGear; // 装备信息(部位 -> 物品ID)public int saveVersion; // 数据版本号,用于后续升级兼容// 构造函数,初始化默认值public PlayerData(string name, int lvl){playerName = name;level = lvl;gold = 0;inventoryItems = new List<string>();equippedGear = new Dictionary<string, int>();saveVersion = 1; // 初始版本}// 示例:添加物品public void AddItem(string item){inventoryItems.Add(item);}// 示例:升级public void LevelUp(){level++;Debug.Log($"玩家 {playerName} 升级到等级 {level}");}
}

2️⃣ 安全加密:EncryptionUtility.cs

切记:永远不要用明文存储数据!

我们采用 AES(Advanced Encryption Standard) 对称加密算法,结合CBC模式和PKCS7填充,确保数据安全。

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;public static class EncryptionUtility
{// 🔐 演示用密钥(256位 = 32字节)private static readonly byte[] Key = Encoding.UTF8.GetBytes("YourVeryStrongAndSecretKey123456");// 🔐 演示用IV(128位 = 16字节)private static readonly byte[] IV = Encoding.UTF8.GetBytes("AnotherSecretIV1");/// <summary>/// 加密字符串/// </summary>public static string Encrypt(string plainText){if (string.IsNullOrEmpty(plainText)) return string.Empty;using (Aes aesAlg = Aes.Create()){aesAlg.Key = Key;aesAlg.IV = IV;aesAlg.Mode = CipherMode.CBC;aesAlg.Padding = PaddingMode.PKCS7;ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);using (MemoryStream msEncrypt = new MemoryStream()){using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)){using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)){swEncrypt.Write(plainText);}}byte[] encryptedBytes = msEncrypt.ToArray();return Convert.ToBase64String(encryptedBytes); // 转为Base64便于存储}}}/// <summary>/// 解密字符串/// </summary>public static string Decrypt(string cipherText){if (string.IsNullOrEmpty(cipherText)) return string.Empty;byte[] cipherBytes;try{cipherBytes = Convert.FromBase64String(cipherText);}catch (FormatException){Debug.LogError("解密失败:输入字符串不是有效的Base64格式。");return string.Empty;}using (Aes aesAlg = Aes.Create()){aesAlg.Key = Key;aesAlg.IV = IV;aesAlg.Mode = CipherMode.CBC;aesAlg.Padding = PaddingMode.PKCS7;ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);using (MemoryStream msDecrypt = new MemoryStream(cipherBytes)){using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)){using (StreamReader srDecrypt = new StreamReader(csDecrypt)){return srDecrypt.ReadToEnd();}}}}}
}

3️⃣ 异步文件操作:AsyncFileUtility.cs 

using UnityEngine;
using System.IO;
using System.Threading.Tasks;public static class AsyncFileUtility
{private static readonly string _saveDirectory = Application.persistentDataPath;/// <summary>/// 异步写入加密数据/// </summary>public static async Task WriteAllTextAsync(string encryptedData, string fileName){string filePath = Path.Combine(_saveDirectory, fileName);try{await File.WriteAllTextAsync(filePath, encryptedData);Debug.Log($"数据已成功异步写入到: {filePath}");}catch (System.Exception e){Debug.LogError($"异步写入文件失败({filePath}): {e.Message}");}}/// <summary>/// 异步读取加密数据/// </summary>public static async Task<string> ReadAllTextAsync(string fileName){string filePath = Path.Combine(_saveDirectory, fileName);if (!File.Exists(filePath)){Debug.LogWarning($"文件不存在: {filePath}");return null;}try{string encryptedData = await File.ReadAllTextAsync(filePath);Debug.Log($"数据已成功异步从: {filePath} 读取。");return encryptedData;}catch (System.Exception e){Debug.LogError($"异步读取文件失败({filePath}): {e.Message}");return null;}}
}

4️⃣ 核心管理器:DataManager.cs 

 

using UnityEngine;
using System;
using System.Threading.Tasks;public class DataManager : MonoBehaviour
{public static DataManager Instance { get; private set; }private PlayerData _currentPlayerData;private const string PLAYER_SAVE_FILE = "playerSave.json";// 数据加载完成事件,用于通知其他模块public static event Action<PlayerData> OnDataLoaded;void Awake(){if (Instance == null){Instance = this;DontDestroyOnLoad(gameObject); // 场景切换不销毁}else{Destroy(gameObject);}}void Start(){LoadGameAsync(); // 启动时自动加载}/// <summary>/// 异步加载游戏数据/// </summary>public async void LoadGameAsync(){Debug.Log("开始异步加载游戏数据...");string encryptedJson = await AsyncFileUtility.ReadAllTextAsync(PLAYER_SAVE_FILE);PlayerData loadedData = null;if (!string.IsNullOrEmpty(encryptedJson)){string jsonString = EncryptionUtility.Decrypt(encryptedJson);if (!string.IsNullOrEmpty(jsonString)){try{loadedData = JsonUtility.FromJson<PlayerData>(jsonString);// TODO: 可在此处添加版本兼容处理}catch (System.Exception e){Debug.LogError($"反序列化失败: {e.Message}");}}}_currentPlayerData = loadedData ?? new PlayerData("新玩家", 1);Debug.Log(loadedData != null ? "加载存档成功" : "创建新玩家");OnDataLoaded?.Invoke(_currentPlayerData);}/// <summary>/// 异步保存游戏数据/// </summary>public async void SaveGameAsync(){if (_currentPlayerData == null) return;Debug.Log("开始异步保存...");string jsonString = JsonUtility.ToJson(_currentPlayerData);string encryptedJson = EncryptionUtility.Encrypt(jsonString);await AsyncFileUtility.WriteAllTextAsync(encryptedJson, PLAYER_SAVE_FILE);Debug.Log("保存完成");}/// <summary>/// 获取当前玩家数据/// </summary>public PlayerData GetCurrentPlayerData() => _currentPlayerData;// 建议在暂停或后台时保存void OnApplicationPause(bool pauseStatus){if (pauseStatus) SaveGameAsync();}void OnApplicationQuit(){SaveGameAsync(); // 注意:异步可能无法保证完成}
}

在场景中创建一个空 GameObject(如命名为 DataManager),并挂载 DataManager.cs 脚本。 

 

http://www.dtcms.com/a/308787.html

相关文章:

  • HTM 5 的离线储存的使用和原理
  • Unity游戏开发中的3D数学基础详解
  • MATLAB 2025a的下载以及安装,安装X310的测试附加功能(附加安装包)
  • 因为想开发新项目了~~要给老Python项目整个虚拟环境
  • 旋转花键在机械加工中心ATC装置中有什么优势?
  • 01 全基因组关联分析原理
  • vlan技术
  • 【PHP属性详解:从基础到只读的完全指南】
  • 企业智脑1.3.1技术升级全面解读:AI笔记引擎如何重塑企业知识管理范式
  • 计算机系统基础与操作系统笔记
  • Spring Boot Admin 监控模块笔记-实现全链路追踪
  • 另外几种语言挑战100万行字符串文本排序
  • Web开发-PHP应用原生语法全局变量数据接受身份验证变量覆盖任意上传(代码审计案例)
  • 风力发电场景下设备状态监测与智能润滑预测性维护策略
  • 【Python气象可视化】用Cartopy+Matplotlib绘制青藏高原涡移动轨迹图(附完整代码+颜色渐变时间轴)
  • 数据库学习--------数据库日志类型及其与事务特性的关系
  • 题目:BUUCTF之rip(pwn)
  • [算法]Leetcode3487
  • 【高等数学】第七章 微分方程——第五节 可降阶的高阶微分方程
  • 第三章·数据链路层
  • 前端路由深度解析:Hash 模式 vs. History 模式
  • 数字化应急预案:构筑现代安全防线
  • 实时语音流分段识别技术解析:基于WebRTC VAD的智能分割策略
  • MySQL 中的事务隔离级别有哪些?分别解决什么问题?
  • 图结构知识构造方法详解 ——面向垂直领域的高效知识库构建方案
  • CentOS 7 编译 Redis 6.x 完整教程(解决 GCC 版本不支持 C11)
  • lesson29:Python元类与抽象类深度解析:从接口定义到元编程实践
  • mysql 日志机制
  • Java 接口(上)
  • 哈希相关的模拟实现