|
前言
最近把前同事 @Mike Jinhua 写的配表工具整理了一下,网上的Unity配表工具有很多,也算分享一下另一种实现吧。
工具介绍
生成工具使用python3写的,python写工具有几个优点,首先语言是跨平台的,常用IDE也是跨平台的。然后python是解释性语言,可以直接调试,可以快速测试功能。python的下载链接如下
IDE使用的是pycharm
关于pycharm的配置网上介绍的文章有很多,参考一篇就可以了。最后工具打开界面如下所示
python工具使用了第三方库xlrd, 通过pycharm,可以很方便的导入第三方库
python工具使用的话可能需要设置一下Excel文件目录,生成的二进制文件目录,代码生成目录,在Config.py文件中,下面三个路径需要自定义下,当然也可以使用默认目录。- # Excel文件目录
- EXCEL_DIR = "./Excel"
- # 数据生成路径
- UnityDataDir = "./../ExcelTest/Assets/StreamingAssts/Config/"
- # 代码生成路径
- UnityCodeDir = "./../ExcelTest/Assets/Scripts/Config/"
复制代码 工具会在Unity中生成一个二进制数据文件和相应的所有配表类。如下图所示
外部调用的话,只要几行代码就可以初始化所有的表格数据。- string configpath = Application.streamingAssetsPath + "/Config/Config.data";
- ConfigManager.LoadConfig(configpath);
复制代码 这个配表工具能做到自动化,数据的配置可以在Excel内完成。程序不需要再写其他代码,只要通过生成的配置类读取相应的数据就可以了。
既然在Excel内就能配置数据,那么把视角转向Excel表吧。打开某一张配置表,如下图所示
每个数据表的表头有5行
第一行是生成的代码的注释第二行有三个字段可以选择CS,C,S, 分别代表这个字段是客户端服务器通用,只是客户端使用,还是只能是服务器使用。通过这个字段筛选,可以避免生成数据的冗余第三行是生成的字段类型,目前列举了N种类型
int 整型
float 浮点型
bool bool值
string 字符串
list[int] 整型列表
list[float] 浮点数列表
list[string] 字符串列表
map[int|int] int为key, int为值的字典
map[int|float] int为key, float为值的字典
map[int|string] int为key, string为值的字典
map[string|int] string为key, int为值的字典
map[string|float] string为key, float为值的字典
map[string|string] string为key, string为值的字典 通过选择这些类型,可以生成常用的数据类型
第四行是生成的字段名字(避免重名)第五个字段是设置生成的配表类有几个Key值
没有Key的情况下,生成的类没有读取函数,只能用List遍历所有的数据
有一个Key的情况下,生成的类数据用Dictionary来管理,可以通过这个Key值获取数据
在有多个Key的情况下,生成的类数据用List来管理,可以通过多个Key值的获取函数获取表格数据
打上Key关键字的字段一般使用int, string这两个基本类型 需要特殊说明的是,在Excel中,对于数组类型字段,需要使用默认的分隔符对于List字段,分隔符是使用的 ';' (分号)
对于Map字段,一级分隔符是 '|' (竖斜杠), 二级分隔符是 ';' (分号) 具体代码实现
1. Excel2Unity表格生成工具
对于这个python写的表格工具,主要的用来生成二进制数据和代码文本。
A. 二进制文件生成
笔者在整理代码的过程中,对于python生成二进制文件不了解,通过Google学习了python对二进制流的操作
python通过struct类对二进制数据进行读写, 文档如下
在这篇文档中,主要是要确定对于不同的数据写入需要什么格式,主要是下面这张表
目前这个表格工具其实只用到了4种类型int, float, bool, string
在python3中,写入数据使用如下代码 struct.pack(format, val)
对于int类型,使用的Format是"i", 流入的数据占用4个字节, 在python中代码如下bytes = struct.pack(format, int(val))对于float类型,和int类型相似,使用的Format是"f", 流入的数据占用4个字节, 在python中代码如下 bytes = struct.pack(format, float(val))对于bool类型,使用的Format是"?", 流入的数据占用1个字节,在python中代码如下 bytes = struct.pack(format, bool(val))对于特殊的string类型,根据表格显示,使用的Format是"s", 流入的数据只占用1个字节. 这里就有需要注意的地方了。在配表列出的数据类型中,除了列出的int, float, bool 三种类型,其他的类型流化成二进制数据的时候全部使用的是string流入。看看如下的python代码
- newval = val.encode()
- vallen = len(newval)
- lenbyte = struct.pack("i", vallen)
- strformat = str(vallen) + format
- valbyte = struct.pack(strformat, newval)
- bytes = lenbyte + valbyte
复制代码 上面的代码中,对于Excel表格中读取的单元格数据,首先得到这块数据的所占字节数,然后用int类型流入这个字节数,然后通过字节数和"s"拼装成最终的字符串格式,例如,字节数是20个,那么最终的字符串格式就是"20s", 然后再用struct.pack函数流入二进制数据。
也就是说,对于一个string类型,流入的二进制数据包括占用4个字节的数据长度,以及这么多数据长度的字节。由两部分组成。
完整的python函数如下所示- @staticmethod
- def Encode2Bytes(format, val):
- if format == "i":
- bytes = struct.pack(format, int(val))
- elif format == "f":
- bytes = struct.pack(format, float(val))
- elif format == "?":
- bytes = struct.pack(format, bool(val))
- elif format == "s":
- newval = val.encode()
- vallen = len(newval)
- lenbyte = struct.pack("i", vallen)
- strformat = str(vallen) + format
- valbyte = struct.pack(strformat, newval)
- bytes = lenbyte + valbyte
-
- return bytes
复制代码 由于只生成一个二进制文件,所以所有文件的所有数据都会拼接起来,保存在一个二进制文件里面。
B. 代码生成
对于代码的生成,就是普通的字符串拼接,然后保存在文件中。需要注意的是:- file = open(path, "wb")
- file.write(filecontent.encode())
- file.close()
复制代码 对于生成的字符串filecontent, 需要使用encode()函数编码成utf-8格式,encode的默认参数就是编码成utf-8格式
2. Unity数据读取
在Unity中读取生成的二进制文件,需要准备几个基础类,拿出一个生成的配表文件类- public class Test1Cfg
- {
- public int ID; // int类型
- public float HP; // float类型
- public bool HasUse; // bool类型
- public string Name1; // string类型
- public string Name2; // string类型
- public List<int> Vec1; // int数组
- public List<float> Vec2; // float数组
- public List<string> Vec4; // string数组
- public Dictionary<int, int> Map1; // intint字典
- public Dictionary<int, float> Map2; // intfloat字典
- public Dictionary<int, string> Map4; // intstring字典
- public Dictionary<string, int> Map5; // stringint字典
- public Dictionary<string, float> Map6; // stringfloat字典
- public Dictionary<string, string> Map8; // stringstring字典
- public void Deserialize (DynamicPacket packet)
- {
- ID = packet.PackReadInt32();
- HP = packet.PackReadFloat();
- HasUse = packet.PackReadBoolean();
- Name1 = packet.PackReadString();
- Name2 = packet.PackReadString();
- Vec1 = SheetGenCommonFunc.GetListInt(packet.PackReadString());
- Vec2 = SheetGenCommonFunc.GetListFloat(packet.PackReadString());
- Vec4 = SheetGenCommonFunc.GetListString(packet.PackReadString());
- Map1 = SheetGenCommonFunc.GetDictIntInt(packet.PackReadString());
- Map2 = SheetGenCommonFunc.GetDictIntFloat(packet.PackReadString());
- Map4 = SheetGenCommonFunc.GetDictIntString(packet.PackReadString());
- Map5 = SheetGenCommonFunc.GetDictStringInt(packet.PackReadString());
- Map6 = SheetGenCommonFunc.GetDictStringFloat(packet.PackReadString());
- Map8 = SheetGenCommonFunc.GetDictStringString(packet.PackReadString());
- }
- }
复制代码 对于python的二进制写入,C#这边的二进制读取分别
使用DynamicPacket的PackReadInt32()函数读取int数据
使用DynamicPacket的PackReadFloat()函数读取float数据
使用DynamicPacket的PackReadBoolean()函数读取boolean数据
使用DynamicPacket的PackReadString()函数读取string数据。
由于string数据流入比较特殊,所以特别看下PackReadString()这个函数的实现- public string PackReadString()
- {
- int count = this.PackReadInt32();
- if (count == 0)
- return &#34;&#34;;
- byte[] bytes = this.PackReadBytes(count);
- return Encoding.UTF8.GetString(bytes);
- }
- public int PackReadInt32()
- {
- return this.mReader.ReadInt32();
- }
- public byte[] PackReadBytes(int count)
- {
- byte[] array = new byte[count];
- for (int i = 0; i < count; i++)
- {
- array[i] = this.mReader.ReadByte();
- }
- return array;
- }
复制代码 首先调用PackReadInt32()函数读取字节数,然后调用PackReadBytes()函数读取出二进制数据流,通过Encoding.UTF8.GetString(bytes)函数获取utf-8格式的string数据。注意到mReader变量,所有的数据都是通过这个变量来读取的,这个变量是BinaryReader类定义的。
对于DynamicPacket这个类的初始化,如下所示- public BinaryWriter mWriter;
- public BinaryReader mReader;
- public MemoryStream mMemStream;
- public DynamicPacket(byte[] bytes)
- : this()
- {
- this.mMemStream.Write(bytes, 0, bytes.Length);
- this.mMemStream.Seek(0L, SeekOrigin.Begin);
- }
- public DynamicPacket()
- {
- this.mMemStream = new MemoryStream();
- this.mReader = new BinaryReader(this.mMemStream);
- this.mWriter = new BinaryWriter(this.mMemStream);
- }
复制代码 DynamicPacket把表格二进制文件读取,通过BinaryReader来读取所有的二进制数据。通过这个DynamicPacket类,可以流化出所有的数据。
C#进行二进制数据读取不复杂,具体可以看下github的工程代码,最后给出这个工具的github地址。
项目github地址
其他的导表工具实现
github成熟工具 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|