[unity]一种保存存档系统的实现

 如题,可以通过实现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());
        }
         */
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值