【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili
教程源地址:https://www.udemy.com/course/2d-rpg-alexdev/
本章节实现了快速删除存档和加密存档
以下是加密前和加密后的对比
SaveManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
//2024.11.25
public class SaveManager : MonoBehaviour
{
public static SaveManager instance;
[SerializeField] private string fileName;
[SerializeField] private bool encryptData;
private GameData gameData;
private List<ISaveManager> saveManagers = new List<ISaveManager>();
private FileDataHandler dataHandler;
[ContextMenu("Delete save file")]
private void DeleteSaveData()
{
dataHandler = new FileDataHandler(Application.persistentDataPath, fileName, encryptData);
dataHandler.Delete();
}
private void Awake()
{
if (instance != null)
Destroy(instance.gameObject);
else
instance = this;
}
private void Start()
{
dataHandler = new FileDataHandler(Application.persistentDataPath,fileName, encryptData);
saveManagers = FindAllSaveManagers();
LoadGame();
}
public void NewGame()
{
gameData = new GameData();
}
public void LoadGame()
{
gameData = dataHandler.Load();
if (this.gameData == null)
{
Debug.Log("没有找到存档");
NewGame();
}
foreach (ISaveManager saveManager in saveManagers)
{
saveManager.LoadData(gameData);
}
}
public void SaveGame()
{
foreach(ISaveManager saveManager in saveManagers)
{
saveManager.SaveData(ref gameData);
}
dataHandler.Save(gameData);
}
private void OnApplicationQuit()
{
SaveGame();
}
private List<ISaveManager> FindAllSaveManagers()
{
IEnumerable<ISaveManager> saveManagers = FindObjectsOfType<MonoBehaviour>(true).OfType<ISaveManager>();
return new List<ISaveManager>(saveManagers);
}
}
FileDataHandler.cs
Save
方法
- 功能:将
GameData
数据保存到指定路径的文件中。 - 核心逻辑:
- 创建完整路径:通过
Path.Combine
组合文件夹路径和文件名。 - 确保文件夹存在:调用
Directory.CreateDirectory
确保路径中的文件夹被创建。 - 序列化数据:使用
JsonUtility.ToJson
将GameData
对象转为 JSON 格式的字符串。 - 加密数据(可选):如果
encrypData
为true
,调用EncryptDecrypt
方法加密数据。 - 写入文件:通过
FileStream
和StreamWriter
写入数据到文件。 - 异常处理:捕获并报告文件操作可能抛出的异常。
- 创建完整路径:通过
Load
方法
- 功能:从文件中读取数据并反序列化为
GameData
对象。 - 核心逻辑:
- 创建完整路径:和
Save
方法类似,通过Path.Combine
拼接路径。 - 检查文件是否存在:通过
File.Exists
判断文件是否存在。 - 读取数据:使用
FileStream
和StreamReader
读取文件内容。 - 解密数据(可选):如果
encrypData
为true
,调用EncryptDecrypt
解密数据。 - 反序列化:使用
JsonUtility.FromJson
将 JSON 字符串解析为GameData
对象。 - 异常处理:捕获读取过程中的异常并报告。
- 创建完整路径:和
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.IO;
//2024.11.27
public class FileDataHandler
{
private string dataDirPath = "";//数据文件夹路径
private string dataFileName = "";//数据文件名
private bool encrypData=false;//是否加密数据
private string codeWord = "FuNignNa";//加密密码
public FileDataHandler(string _dataDirPath, string _dataFileName, bool encrypData)
{
dataDirPath = _dataDirPath;
dataFileName = _dataFileName;
this.encrypData = encrypData;
}
public void Save(GameData _data)
{
string fullPath = Path.Combine(dataDirPath, dataFileName);
try
{
Directory.CreateDirectory(Path.GetDirectoryName(fullPath));//确保路径中的文件夹被创建
string dataToStore = JsonUtility.ToJson(_data, true);//将数据转换为json格式
if (encrypData)
dataToStore = EncryptDecrypt(dataToStore);//加密数据
using (FileStream stream = new FileStream(fullPath, FileMode.Create))
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(dataToStore);
}
}
}
catch (Exception e)
{
Debug.LogError("保存数据错误: " + fullPath + "\n" + e);
}
}
public GameData Load()
{
string fullPath = Path.Combine(dataDirPath, dataFileName);//找到文件路径
GameData loadData = null;
if (File.Exists(fullPath))
{
try
{
string dataToLoad = "";
using (FileStream stream = new FileStream(fullPath, FileMode.Open))//打开文件
{
using (StreamReader reader = new StreamReader(stream))//读取文件
{
dataToLoad = reader.ReadToEnd();//读取文件
}
}
if (encrypData)
dataToLoad = EncryptDecrypt(dataToLoad);//解密数据
loadData = JsonUtility.FromJson<GameData>(dataToLoad);
}
catch (Exception e)
{
Debug.LogError("读取数据错误: " + fullPath + "\n" + e);
}
}
return loadData;
}
public void Delete()//删除数据
{
string fullPath = Path.Combine(dataDirPath, dataFileName);//找到文件路径
if (File.Exists(fullPath))//如果文件存在就删除s
File.Delete(fullPath);
}
private string EncryptDecrypt(string _data)//加密解密
{
string modifiedData = "";//修改后的数据
for (int i = 0; i < _data.Length; i++)
{
modifiedData += (char)(_data[i] ^ codeWord[i % codeWord.Length]);
}
return modifiedData;
}
}