Unity实现游戏存档框架
作者:hackerzhuli 时间:2023-02-10 13:05:15
最近重构了一下我的存档框架。我在这里对实现方法进行简单的解析。注意这里主要演示算法,所以,效率上并不是最佳。一个游戏中,可能有成百上千个物体需要存储,而且有几十种类型,接下来就用一个简单的例子来解释。一个很简单的例子,有一个Unit(单位)类型,有一个Inventory(背包)类型,有一个Item(道具)类型。
接下来先介绍框架中最重要的接口,ISavable,表示这个类型可以存档
public interface ISavable{
uint Id {get; set;}
Type DataType {get;} // 存档数据类型
Type DataContainerType {get;} // 存档数据容器类型
void Read(object data);
void Write(object data);
}
ISavableContainer,用来返回一组ISavable的容器:
public interface ISavableContainer{
IEnumerable<ISavable> Savables;
}
IId, 具有Id的接口:
public interface IId
{
uint Id {get; set;}
}
SaveEntity, 这是一个MonoBehaviour,将这个组件放到需要存档的GameObject上就可以实现该GameObject的存档了,这是最核心的类之一:
public class SaveEntity : MonoBehaviour{
public void Save(SaveDataContainer container){
foreach(ISavable savable in GetSavables()){
if(savable.DataContainerType = container.GetType()){
IId newData = Activator.CreateInstance(savable.DataType) as IId;
newData.Id = savable.Id;
savable.Write(newData);
container.SetData(newData);
}
}
}
public void Load(SaveDataContainer container){
foreach(ISavable savable in GetSavables()){
if(savable.DataContainerType = container.GetType()){
IId data = container.GetData(savable.Id);
savable.Read(data);
}
}
}
public IEnumerable<ISavable> GetSavables(){
foreach(ISavable savable in GetComponents<ISavable>()){
yield return savable;
}
foreach(ISavable savableContainer in GetComponents<ISavableContainer>()){
foreach(ISavable savable in savableContainer.Savables){
yield return savable;
}
}
}
}
SaveFile代表一个文件
[Serializable]
public class SaveFileData{
public uint CurId;
public string DataContainer;
}
// 代表一个存档文件
public class SaveFile: MonoBehaviour{
// 包含实际数据的数据类
private SaveDataContainer _saveDataContainer;
private uint _curId;
public string Path{get;set;}
public SaveDataContainer SaveDataContainer{get{return _saveDataContainer;}}
private uint NextId{get{return ++_curId;}}
// 得到场景里所有的SaveEntity
private IEnumerable<SaveEntity> GetEntities(){
// 实现略过
}
// 将场景物体中的数据存入到_saveDataContainer中
public void Save<T>() where T:SaveDataContainer, new()
{
// 一轮Id赋值,保证Id为0的所有ISavable都赋值一个新Id
foreach(SaveEntity entity in Entities){
foreach (Savable savable in entity.GetSavables()){
if(savable.DataContainerType == typeof(T)){
if(savable.Id == 0){
savable.Id = NextId;
}
}
}
}
T dataContainer = new T();
foreach(SaveEntity entity in Entities){
entity.Save(this, dataContainer);
}
_saveDataContainer = dataContainer;
}
// 将_saveDataContainer中的数据载入到场景物体中
public void Load(){
foreach(SaveEntity entity in Entities){
entity.Load(this, _saveDataContainer);
}
}
public void LoadFromFile<T>() where T:SaveDataContainer
{
string json = File.ReadAllText(Path);
SaveFileData data = JsonUtility.FromJson<SaveFileData>(json);
_saveDataContainer = JsonUtility.FromJson<T>(data.DataContainer);
_curId = data.CurId;
}
public void SaveToFile(){
SaveFileData data = new SaveFileData();
data.CurId = _curId;
data.DataContainer = JsonUtility.ToJson(_saveDataContainer);
string json = JsonUtility.ToJson(data);
File.WriteAllText(Path, json);
}
}
SaveDataContainer:
// 这个类型存储了实际的数据,相当于是一个数据库
[Serializable]
public class SaveDataContainer{
// 这个中存储这实际物体的数据,需要将这个字典转换成数组并序列化
private Dictionary<uint, IId> _data;
public Dictionary<unit, IId> Data{get{return _data}}
public IId GetData(uint id){
return _data[id];
}
public void SetData(IId data){
_data[data.Id] = data;
}
}
来源:https://blog.csdn.net/mynameiszhuli/article/details/104026295
标签:Unity,游戏存档
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
用C#缩小照片上传到各种空间的具体方法
2022-03-28 02:29:18
JAVA实现简单系统登陆注册模块
2021-11-05 05:41:50
![](https://img.aspxhome.com/file/2023/8/108398_0s.jpg)
Android监听键盘状态获取键盘高度的实现方法
2023-12-02 16:44:17
Intellij IDEA 2019 最新乱码问题及解决必杀技(必看篇)
2023-12-04 18:30:02
![](https://img.aspxhome.com/file/2023/6/106156_0s.jpg)
SpringBoot中Jackson日期格式化技巧分享
2022-05-21 01:40:24
基于Ok+Rxjava+retrofit实现断点续传下载
2021-08-27 02:21:49
![](https://img.aspxhome.com/file/2023/5/108435_0s.jpg)
Android 如何定制vibrator的各种震动模式M 具体方法
2023-08-13 02:09:01
Android系统工具类详解
2023-07-12 22:11:57
Mybatis无法获取带有下划线前缀的字段的值问题
2023-07-20 10:06:33
![](https://img.aspxhome.com/file/2023/3/62173_0s.png)
利用Android画圆弧canvas.drawArc()实例详解
2022-05-21 08:45:54
![](https://img.aspxhome.com/file/2023/4/122064_0s.png)
Unity动画混合树实例详解
2022-06-17 14:41:27
![](https://img.aspxhome.com/file/2023/8/104298_0s.gif)
Java 获取网站图片的示例代码
2022-03-11 14:52:44
![](https://img.aspxhome.com/file/2023/9/67969_0s.jpg)
struts2 validation.xml 验证规则代码解析
2021-09-14 22:01:27
C#实现实体类和XML相互转换
2023-06-16 04:37:32
C#值类型、引用类型中的Equals和==的区别浅析
2022-09-05 23:04:24
![](https://img.aspxhome.com/file/2023/3/98283_0s.png)
25个最好的免费Eclipse插件
2021-09-21 10:56:24
![](https://img.aspxhome.com/file/2023/2/67642_0s.jpg)
android,不显示标题的方法小例子
2023-07-10 17:14:36
详解c# 类的构造方法
2023-02-10 17:17:19
Spring EL表示式的运用@Value说明
2023-03-05 02:33:19
C# 指针内存控制Marshal内存数据存储原理分析
2021-09-22 04:05:00