如题,可以通过实现ISavable接口方便地保存
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.IO;
using System;
using UnityEngine;
using System.Linq;
namespace Script.Systems.SaveSystem
{
public class Save : MonoBehaviour
{
public static string savePath = Application.dataPath.Replace("Assets", "") + "Save\\";
public static string currentSave = "default";
// 使用 HashSet 存储 ISaveable 对象
public static HashSet<ISaveable> saveables = new HashSet<ISaveable>();
// 扫描指定路径下的所有文件(递归扫描子目录),排除 .meta 文件
public static List<string> ScanAllFiles(string directoryPath)
{
List<string> fileList = new List<string>();
try
{
// 获取指定目录下的所有文件
string[] files = Directory.GetFiles(directoryPath, "*.*", SearchOption.AllDirectories);
// 过滤掉 .meta 文件
foreach (string file in files)
{
if (!file.EndsWith(".meta", StringComparison.OrdinalIgnoreCase))
{
fileList.Add(file);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error scanning directory: {ex.Message}");
}
return fileList;
}
public static string Load(string path, bool isAbsolutePath = false)
{
// 确保路径存在
string finalPath;
if (isAbsolutePath)
{
finalPath = path;
}
else
{
finalPath = savePath + currentSave + "\\" + path;
}
string directory = Path.GetDirectoryName(finalPath);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory); // 创建路径
}
// 如果文件不存在,则创建一个空文件
if (!File.Exists(finalPath))
{
File.Create(finalPath).Close(); // 创建文件并关闭流
}
// 读取文件内容并返回
return File.ReadAllText(finalPath);
}
public static JObject LoadJObject(string path, bool isAbsolutePath = false)
{
return JObject.Parse(Load(path, isAbsolutePath));
}
public static void SaveFile(string path, string content)
{
// 确保路径存在
string finalPath = savePath + currentSave + "\\" + path;
string directory = Path.GetDirectoryName(finalPath);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory); // 创建路径
}
// 写入内容到文件
File.WriteAllText(finalPath, content);
}
public static void SaveJObject(string path, JObject jObject)
{
// 将 JObject 转换为 JSON 字符串
string jsonContent = jObject.ToString();
// 调用 Save 方法保存内容
SaveFile(path, jsonContent);
}
public static void SaveAll()
{
// 清除旧存档
ClearOldSaves();
string info = $"Saving {saveables.Count} objects...\nSaving Folder Name: {currentSave}";
Debug.Log(info);
info = "files:\n";
foreach (var saveable in saveables)
{
JObject jObject = saveable.Serialize();
jObject.Add("type", saveable.GetType().Name);
SaveJObject(saveable.GetPath(), jObject);
info += saveable.GetPath() + "\n";
}
Debug.Log(info);
Debug.Log("finished");
}
private static void ClearOldSaves()
{
string directoryPath = savePath + currentSave;
if (Directory.Exists(directoryPath))
{
try
{
// 获取目录下的所有文件
string[] files = Directory.GetFiles(directoryPath);
// 删除所有文件
foreach (string file in files)
{
File.Delete(file);
}
Debug.Log("Old saves cleared.");
}
catch (Exception ex)
{
Debug.LogError($"Error clearing old saves: {ex.Message}");
}
}
}
// 加载所有保存的实体
public static void LoadAll()
{
Dictionary<string, Type> typeDic = new Dictionary<string, Type>();
// 获取所有实现了 ISaveable 接口的类
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => t.IsClass && typeof(ISaveable).IsAssignableFrom(t));
foreach (var type in types)
{
typeDic[type.Name] = type;
}
var fileList = ScanAllFiles(savePath);
foreach (var filePath in fileList)
{
JObject jObject = LoadJObject(filePath, isAbsolutePath:true);
string typeName = jObject["type"].Value<string>();
jObject.Remove("type");
if (typeDic.ContainsKey(typeName))
{
Type type = typeDic[typeName];
ISaveable saveable;
try
{
Debug.Log(typeName);
if (typeof(MonoBehaviour).IsAssignableFrom(type))
{
GameObject example = new GameObject();
saveable = example.AddComponent(type) as ISaveable;
}
else
{
saveable = Activator.CreateInstance(type) as ISaveable;
}
}
catch(Exception ex)
{
string info = $"Failed to create instance of type: {typeName}\n{ex.Message}";
Debug.LogError(info);
saveable = null;
continue;
}
if (saveable != null)
{
saveable.Deserialize(jObject);
saveables.Add(saveable); // 将加载的对象添加到集合中
}
else
{
Console.WriteLine($"Failed to create instance of type: {typeName}");
}
}
else
{
Console.WriteLine($"Type not found: {typeName}");
}
}
}
}
public interface ISaveable
{
/// <summary>
/// 序列化对象为JObject。
/// </summary>
/// <returns>表示对象的JObject。</returns>
public JObject Serialize();
/// <summary>
/// 从JObject反序列化对象。
/// </summary>
/// <param name="jObject">表示对象的JObject。</param>
public void Deserialize(JObject jObject);
/// <summary>
/// 获取对象的保存路径。
/// </summary>
/// <returns>对象的保存路径。</returns>
public string GetPath();
/// <summary>
/// 注册对象到保存系统。
/// </summary>
public void Register();
/// <summary>
/// 从保存系统中注销对象。
/// </summary>
public void Unregister();
// 示例
/*
// 序列化方法
public JObject Serialize()
{
if (IsDestroyed)
{
return null;
}
JObject entityJson = new JObject...
return entityJson;
}
// 反序列化方法
public void DeserializeToVector3(JObject jObject)
{
EntityID = jObject["EntityID"].ToString();
Name = jObject["Name"].ToString();
Description = jObject["Description"].ToString();
EvasionValue = (float)jObject["EvasionValue"];
IsDestroyed = false;
}
public string GetPath()
{
return "Entity\\" + EntityID + ".json";
}
public void Register()
{
Save.instanceIDToSaveable.Add(this.GetHashCode(), this);
}
public void Unregister()
{
Save.instanceIDToSaveable.Remove(this.GetHashCode());
}
*/
}
}