特点:
- 支持主流数据与容器,包括Vector3、Color、Texture2D、Sprite等等。
- 支持父类装子类数据的序列化和反序列化。
- excel一键生成与读取数据持久化数据。
- 高性能,全程二进制数据读取储存。
- 低耦合,随用随取。
- 便捷,全程一键生成,一行调用。
资源:github
前版本: writer 1.0
更新:
- 在原有xml生成上添加特性生成,添加AutoWrite特性即可一键生成。
- 添加对泛型容器套泛型容器的支持,例如List<List<float>>()。
- 新增excel表格自动化处理工具
一、序列化数据声明
在Data中声明并标记AutoWrite的特性即可
[AutoWrite]
public class PlayerData
{
public long id;
public string name;
}
ps: ReadWrite文件夹下为另一程序集,无法引用主程序集的类与方法,所以推荐将所有有关数据的都声明在一起
当然也可以直接使用主程序集或自己另建一个程序集(引用一下BinaryReadWrite),然后需要在WriterManage中的assmblyList中添加一下。
不推荐直接使用主程序集,因为游戏开始时会遍历所选程序集,主程序集中大部分都是不必要的数据,全部遍历会浪费时间
public static List<(string savePath, Assembly assembly)> assemblyList = new List<(string savePath, Assembly assembly)>()
{
(Application.dataPath + "/Scripts/ProjectBase/Writer/ReadWrite/",typeof(Writer).Assembly)
};
- savePath:为序列化脚本储存位置,要为添加程序集下的文件夹
- assembly:要添加的程序集
额外操作:
- 在字段前添加NotWrite特性,即可忽视该字段的序列化与反序列化
public struct InventoryItem
{
public int itemID;
public int itemAmount;
[NotWrite]
public ItemDetails itemDetails;
public InventoryItem(int id,int amount)
{
itemID = id;
itemAmount = amount;
itemDetails = null;
}
}
- 继承ICloneable,实现接口,可以让类像结构体一样克隆一个出来
[AutoWrite]
public class ItemPoolData : ICloneable
{
public InventoryItem item;
public int weight;
[HideInInspector] public int weightIndex;
public ItemPoolData() { }
public ItemPoolData(int id, int amount,int weight)
{
item = new InventoryItem(id, amount);
this.weight = weight;
}
public object Clone()
{
return Utilities.Clone(this);
}
}
二、序列化反序列使用
1. 第一步先生成序列化脚本,点击顶部菜单生成
2. 初始化WriterManage,调用WriterManage.Init()。
public class Main : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
WriterManage.Init();
}
}
ps:无论在任何情况都请先初始化,包括编辑器下要用时也请初始化,所以推荐在游戏开始时直接初始化。
3. 调用WriterManage的API,或者自己声明Writer或Reader序列化反序列化
//WriterManage的API
WriterManage.Init();
PlayerData player = new PlayerData() { id = 0 };
//序列化,返回字节组
byte[] bytes = WriterManage.Instance.Write(player);
//反序列化,返回实例
player = WriterManage.Instance.Read<PlayerData>(bytes);
//框架内有ResMgr,使用其中API直接储存读取数据
//序列化后储存
ResMgr.Instance.SaveWithWriter(player, "Game/PlayerData.data");
//反序列化读取
player = ResMgr.Instance.LoadWithWriter<PlayerData>("Game/PlayerData.data");
//使用自建Writer和Reader
WriterManage.Init();
PlayerData player = new PlayerData() { id = 0 };
//序列化
Writer writer = new Writer();
writer.Write(player);
byte[] bytes = writer.ToArray();
//反序列化
Reader reader = new Reader(bytes);
player = reader.ReadPlayerData();
三、excel表格自动化处理工具
1. 声明生成脚本
using UnityEditor;
using UnityEngine;
public class ItemDataGen
{
[MenuItem("Tools/Game/生成物品数据")]
public static void Gen()
{
WriterManage.Init();
string path = Application.dataPath + "/Editor/Game/ItemData/Data/ItemData.xlsx";
AutoExcelTool.Triger("Game/ItemData", path, AutoType.sigle, GenType.allFile);
}
}
这里使用编辑器顶部菜单栏触发方法,核心方法:
AutoExcelTool.Triger(string savePath, string loadPath, AutoType type = AutoType.sigle, GenType gen = GenType.sigle, Action<string[]> onReadRow = null, Action<DataTable> onReadTable = null, Action<FileInfo> onReadFile = null, bool ifGenScript = true)
- savePath:二进制数据存储位置,在Application.streamingAssetsPath下。
- loadPath:excel文件所在位置,需要全路径。
- type:寻找文件模式,sigle:读取单文件,loadPath为文件全路径(带后缀);all:文件夹下全文件,loadPath为文件夹路径。
- gen:表格读取模式,sigle:单表模式,表中每一个附表都是单独的数据集,附表名为数据脚本类名,相同表名会覆盖前表;allFile,文件模式,全文件为一数据集,文件名为数据脚本名,文件中所有附表都在同一数据集中。
- onReadRow:当读取完一行后触发。
- onReadTable:当读取完一表后触发。
- onReadFile:当读取完一文件后触发。
- ifGenScript:是否自动化生成脚本,修改脚本会重新编译,在只修改数据不改数据结构时,不生成脚本会提升生成速度。
2. 创建excel表格
- 第一行用于编辑时提示该列的类型,生成时无意义,所以为空也无所谓
- 第二行为数据字段名称,生成时数据结构类中字段就是该名称
- 第三行为数据类型,支持float、double、int、long、string、bool、uint、ushort、ulong、List<T>、Dictionary<T,V>、数组(int[])
注意
- 后3种数据容器内的类行只能为前面的类型,不能容器套娃
- 数据容器内的元素用空格区分每一元素,所以不要顺便空格
- 字典用“=”链接键与值
- 只有容器和string可以为空
额外操作
- 在第一行第一格填“#”,可以忽视该附表
- 在第四行及以后的第一格填“#”,可以忽视该行
3. 生成持久化数据
using System;
using System.Collections.Generic;
using System.Text;
using BinaryReadWrite;
namespace ExcelTool
{
public class ItemData : AutoData<ItemData>, ICloneable
{
public int id;
public string name;
public int stack;
public int price;
public List<int> mod;
public int[] attribute;
public Dictionary<string,int> state;
public static string Path = "Game/ItemData/ItemData.data";
public object Clone()
{
return Utilities.Clone(this);
}
public T Clone<T>()
{
return (T)Utilities.Clone(this);
}
}
public static class ItemDataReadWrite
{
public static void WriteItemData(this Writer writer, ItemData value)
{
writer.Write(value.id);
writer.Write(value.name);
writer.Write(value.stack);
writer.Write(value.price);
writer.Write(value.mod);
writer.Write(value.attribute);
writer.Write(value.state);
}
public static ItemData ReadItemData(this Reader reader)
{
ItemData value = new ItemData();
value.id = reader.ReadInt();
value.name = reader.ReadString();
value.stack = reader.ReadInt();
value.price = reader.ReadInt();
value.mod = reader.ReadList<int>();
value.attribute = reader.ReadArray<int>();
value.state = reader.ReadDictionary<string,int>();
return value;
}
}
}
4. 读取持久化数据
WriterManage.Init();
List<ItemData> items = ItemData.Instance;
对就是这么简单!!!
不需要填路劲,不需要读取,WriterManage在游戏开始时已经初始化了,所以一行能读取出来,后续数据生成路劲更改了,也可以自动读取。
ps:
- 推荐单文件模式加文件模式,在数据比较复杂时,后续添加方便,例如:
每一个附表都是不同的物品类型,每一种物品类型用不同的id头数字,例如1000,2000,3000。
工程实践项目:bilibili
联系QQ:1768927122