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

适用于QF的存档系统

存档系统

今天分享一个适用于QF的存档系统

这个系统的优点为

1、轻量化,总共代码不超过400行

2、自动化,基于QF框架,自动注入值

缺点:

1、不能序列化Unity内部类型,如Vector

2、需要给能被序列化的类加上【Serialize】属性

依赖下载

在Unity的包管理器中,输入Newtonsoft.json,下载依赖

模块分析

Storage:工具模块

维护一个数据缓冲区,负责将数据从磁盘中读取到缓冲区中,并且从缓冲区获取数据写入磁盘

using QFramework;namespace EggFramework.Storage
{public interface IStorage : IUtility{void AssignSavePath(string path = "saveData");void ReadFromDisk();void WriteToDisk();T Load<T>(string key, T defaultValue,out bool newValue);void Save<T>(string key, T saveData);void Clear();}
}

接口模块定义如上

FileSystem:系统模块

维护一个保存了存档名的列表,并且负责实际注册数据,加载数据,保存数据

using QFramework;
using System.Collections.Generic;namespace EggFramework.FileSystem
{public interface IFileSystem : ISystem{List<string> FileNames { get; }void Register<T>(BsProperty<T> savable, string name);void Unregister<T>(BsProperty<T> savable);void CreateFile(string fileName);//自动加载当前的存档void LoadFile(string fileName = "File1");void SaveFile();void DeleteFile(string fileName);void DeleteAll();}
}

其中BSProperty定义如下

#region//文件创建者:Egg
//创建时间:09-10 02:24#endregionusing System;
using QFramework;namespace EggFramework.FileSystem
{public sealed class BsProperty<T> : BindableProperty<T>, ISavable{Action ISavable.OnLoad { get; set; } = () => { };Action ISavable.OnSave { get; set; } = () => { };}
}
#region//文件创建者:Egg
//创建时间:09-10 02:23#endregionusing System;namespace EggFramework.FileSystem
{public interface ISavable{Action OnLoad { get; set; }Action OnSave { get; set; }}
}

通过ISavable限制BSProperty,并且通过在框架初始化的时候,将数据注册到FileSystem,加载时,统一将数据注入BSProperty。

Storage实现

using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using UnityEngine;namespace EggFramework.Storage
{public sealed class JsonStorage : IStorage{private string _savePath = "saveData.json";private Dictionary<string, object> _saveData = new();public void ReadFromDisk(){var path = Path.Combine(Application.persistentDataPath, _savePath);Debug.Log(path);if (File.Exists(path)){var json = File.ReadAllText(Path.Combine(Application.persistentDataPath, _savePath));_saveData = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);Debug.Log("读取成功");}else{_saveData.Clear();}}public void WriteToDisk(){var json = JsonConvert.SerializeObject(_saveData);File.WriteAllText(Path.Combine(Application.persistentDataPath, _savePath), json);}public void Save<T>(string key, T saveData){if (saveData == null){Debug.LogWarning("Saving null data");}if (_saveData.TryAdd(key, saveData)){_saveData[key] = saveData;}}public T Load<T>(string key, T defaultValue, out bool newValue){newValue = false;if (!_saveData.TryGetValue(key, out var saveValue)){newValue = true;return defaultValue;}//5月15日补丁,对直接使用的布尔类型区别处理if (typeof(T) == typeof(bool)){return (T)saveValue;}return JsonConvert.DeserializeObject<T>(saveValue.ToString());}public void AssignSavePath(string path = "saveData"){_savePath = path + ".json";}public void Clear(){_saveData.Clear();}}
}

FileSystem实现

using QFramework;
using System.Collections.Generic;
using EggFramework.Storage;
using UnityEngine;namespace EggFramework.FileSystem
{public sealed class FileSystem : AbstractModule, IFileSystem{public List<string> FileNames { get; private set; } = new();private bool _inited;private bool _loaded;private IStorage _storage;private readonly List<ISavable> _savableProperties = new();private readonly Dictionary<ISavable, object> _defaultValues = new();private string _currentFile = string.Empty;public void DeleteFile(string fileName){MakeSureInited();if (FileNames.Contains(fileName)){_storage.AssignSavePath(fileName);_storage.Clear();_storage.WriteToDisk();FileNames.Remove(fileName);Debug.Log("删除成功");}else{Debug.Log("要删除的存档不存在");}}public void DeleteAll(){MakeSureInited();foreach (var fileName in FileNames){DeleteFile(fileName);}}private void MakeSureInited(){if (string.IsNullOrEmpty(_currentFile)){if (FileNames == null){OnInit();}if (FileNames!.Count == 0){FileNames.Add("File1");}_currentFile = FileNames[0];}}private T Load<T>(string key, T defaultValue, out bool isNew){MakeSureInited();return _storage.Load(key, defaultValue, out isNew);}private void LoadFileInner(){MakeSureInited();SaveFileName();//清除缓存区_storage.Clear();//指定路径_storage.AssignSavePath(_currentFile);//加载数据_storage.ReadFromDisk();//为每个已注册值赋值foreach (var savable in _savableProperties){savable.OnLoad?.Invoke();}_loaded = true;}//必須在所有值都註冊完畢後,调用LoadFile,否则无法填充对应的值public void LoadFile(string fileName = "File1"){_currentFile = fileName;LoadFileInner();}/// <summary>///用于将存档名写入文件/// /// </summary>private void SaveFileName(){MakeSureInited();//指定路径_storage.AssignSavePath();//读取磁盘_storage.ReadFromDisk();//写入缓存区_storage.Save(nameof(FileNames), FileNames);//写入磁盘_storage.WriteToDisk();}private void Save<T>(string key, T value){MakeSureInited();_storage.Save(key, value);}public void SaveFile(){if (!_loaded){Debug.LogWarning("需要先加载一个存档才行");return;}_storage.AssignSavePath(_currentFile);_storage.Clear();//依次调用onSave方法,把注册数据写入缓存区foreach (var savable in _savableProperties){savable.OnSave?.Invoke();}//将缓存区中的数据写入文件_storage.WriteToDisk();//将存档名写入文件SaveFileName();}protected override void OnInit(){if (!_inited){_storage = this.GetUtility<IStorage>();_storage.AssignSavePath();FileNames = _storage.Load(nameof(FileNames), new List<string>(), out _);_inited = true;}}//CreateFile有两个重载//可以自定义存档名或者默认存档名public void CreateFile(string fileName){MakeSureInited();if (!FileNames.Contains(fileName)){FileNames.Add("File" + fileName);SaveFileName();}}public void Register<T>(BsProperty<T> savable, string name){if (!_savableProperties.Contains(savable)){_savableProperties.Add(savable);_defaultValues.Add(savable, savable.Value);var saveItem = (ISavable)savable;saveItem.OnLoad += () =>{var value = Load(name, (T)_defaultValues[savable], out var isNew);if (!isNew)savable.Value = value;elsesavable.Value = (T)_defaultValues[savable];};saveItem.OnSave += () => Save(name, savable.Value);}else Debug.Log("重复注册值");}public void Unregister<T>(BsProperty<T> savable){if (_savableProperties.Contains(savable)){_savableProperties.Remove(savable);var saveItem = (ISavable)savable;saveItem.OnLoad = null;saveItem.OnSave = null;}else Debug.Log("重复注销值");}}
}
#region//文件创建者:Egg
//创建时间:09-11 07:30#endregionusing QFramework;namespace EggFramework
{public abstract class AbstractModule : AbstractSystem{}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • python是什么语言写的
  • Go语言并发模式详解:深入理解管道与上下文的高级用法
  • Android-UI设计
  • 数据结构与算法 #时间复杂度 #空间复杂度
  • 可智能生成刺绣图案!武汉纺织大学可视计算与数字纺织团队发布首个多缝线刺绣生成对抗网络模型,被顶级期刊 TVCG 录用
  • 《重生之我在java世界做任务升级》--第二章
  • 机器学习及其应用领域【金融领域】
  • 算法导论——Data Structures and Dynamic Arrays 笔记
  • 进度调度切换
  • HTML+CSS学习笔记
  • Elasticsearch——介绍、安装与初步使用
  • 【UI自动化】前言
  • ELK-01-elasticsearch-8.15.1安装
  • 【LLM】Ollama:本地大模型使用
  • 力扣3290.最高乘法得分
  • Google 是如何开发 Web 框架的
  • Django 博客开发教程 16 - 统计文章阅读量
  • JavaScript实现分页效果
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • rc-form之最单纯情况
  • SSH 免密登录
  • 包装类对象
  • 模型微调
  • 前端知识点整理(待续)
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 深入浅出Node.js
  • 使用 Docker 部署 Spring Boot项目
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • hi-nginx-1.3.4编译安装
  • 大数据全解:定义、价值及挑战
  • 正则表达式-基础知识Review
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • ‌前端列表展示1000条大量数据时,后端通常需要进行一定的处理。‌
  • #android不同版本废弃api,新api。
  • $(function(){})与(function($){....})(jQuery)的区别
  • (03)光刻——半导体电路的绘制
  • (2)nginx 安装、启停
  • (30)数组元素和与数字和的绝对差
  • (Java数据结构)ArrayList
  • (js)循环条件满足时终止循环
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (一)Linux+Windows下安装ffmpeg
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • .NET : 在VS2008中计算代码度量值
  • .net 4.0发布后不能正常显示图片问题
  • .net core webapi Startup 注入ConfigurePrimaryHttpMessageHandler
  • .NET Framework 和 .NET Core 在默认情况下垃圾回收(GC)机制的不同(局部变量部分)
  • .NET 发展历程
  • .NET/C# 编译期能确定的字符串会在字符串暂存池中不会被 GC 垃圾回收掉
  • .NET/C# 如何获取当前进程的 CPU 和内存占用?如何获取全局 CPU 和内存占用?
  • .NET教程 - 字符串 编码 正则表达式(String Encoding Regular Express)
  • .net开发日常笔记(持续更新)
  • .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
  • .net企业级架构实战之7——Spring.net整合Asp.net mvc