测试修改

This commit is contained in:
dingxiaowei
2024-10-15 17:01:49 +08:00
parent a34618ab37
commit 01620a4b0c
+320 -298
View File
@@ -1,298 +1,320 @@
# ExcelTool(Unity打表工具) # ExcelTool(Unity打表工具)
通用CSV/Excel打表工具 通用CSV/Excel打表工具
#### 前言
目前项目中用的csv转json工具,会带来严重的gc性能问题,例如启动加载慢,影响帧率等问题,转成的json数据,我们需要手动写对应的解析模板代码,所以针对以上问题,本通用打表工具应运而生,用二进制数据替代json数据会比较好的解决性能问题,而且能够自动生成对应的模板代码,节省了写重复代码的时间,而且二进制数据比json读取速度更快,文件大小更小。 #### 前言
#### 说明 目前项目中用的csv转json工具,会带来严重的gc性能问题,例如启动加载慢,影响帧率等问题,转成的json数据,我们需要手动写对应的解析模板代码,所以针对以上问题,本通用打表工具应运而生,用二进制数据替代json数据会比较好的解决性能问题,而且能够自动生成对应的模板代码,节省了写重复代码的时间,而且二进制数据比json读取速度更快,文件大小更小。
因为csv有默认的逗号,这跟表中内容配置逗号会有冲突,不利于解析,所有产生了加强版的ExcelTool,读取路径下的csv和excel表格,如果是csv的这先转换成xlsx的excel,然后统一对excel进行数据读取解析操作,生成完之后再把csv生成的excel删掉,确保目录保持原样,所以ExcelTool是CsvTool的升级版
#### 说明
#### 功能
* 支持csv和Excel的打表 因为csv有默认的逗号,这跟表中内容配置逗号会有冲突,不利于解析,所有产生了加强版的ExcelTool,读取路径下的csv和excel表格,如果是csv的这先转换成xlsx的excel,然后统一对excel进行数据读取解析操作,生成完之后再把csv生成的excel删掉,确保目录保持原样,所以ExcelTool是CsvTool的升级版
* 生成对应的数据模板代码
* 支持生成模板代码字段注释 #### 功能
* 生成二进制文件
* 自动将文件拷贝到对应的工程目录 * 支持csv和Excel的打表
* 二进制数据读取 * 生成对应的数据模板代码
* 字段不配置会使用默认数值 * 支持生成模板代码字段注释
* 生成二进制文件
#### 目前支持的字段 * 自动将文件拷贝到对应的工程目录
* 常规的字段,例如intfloatstringboollong,list,intlist,longlist,floatlist,boollist,List<T> 大小写不限 * 二进制数据读取
* 支持自定义字段 vector,例如[1,2,3] * 字段不配置会使用默认数值
* 支持自定义字段 list,其实是vector数组,例如[[1,2,3],[2,3,4],[4,5,6]]
#### 目前支持的字段
#### 效果
![](img/1.gif) * 常规的字段,例如intfloatstringboollong,list,intlist,longlist,floatlist,boollist,List<T> 大小写不限
* 支持自定义字段 vector,例如[1,2,3]
![](img/2.jpg) * 支持自定义字段 list,其实是vector数组,例如[[1,2,3],[2,3,4],[4,5,6]]
相比较json,二进制文件大小只有其1/4
#### 效果
##### 自动生成的模板代码
``` ![](img/1.gif)
/*
* auto generated by tools(注意:千万不要手动修改本文件) ![](img/2.jpg)
* avatarguideTest 相比较json,二进制文件大小只有其1/4
*/
using System; ##### 自动生成的模板代码
using System.IO;
using System.Collections.Generic; ```
using System.Text; /*
using System.Linq; * auto generated by tools(注意:千万不要手动修改本文件)
* avatarguideTest
[Serializable] */
public class avatarguideTest : IBinarySerializable using System;
{ using System.IO;
public int Id { get; set; } using System.Collections.Generic;
public string gender { get; set; } using System.Text;
public float age { get; set; } using System.Linq;
public bool bValue { get; set; }
public List<float> vector { get; set; } [Serializable]
public List<List<float>> Grid { get; set; } public class avatarguideTest : IBinarySerializable
{
public void DeSerialize(BinaryReader reader) public int Id { get; set; }
{ public string gender { get; set; }
Id = reader.ReadInt32(); public float age { get; set; }
gender = reader.ReadString(); public bool bValue { get; set; }
age = reader.ReadSingle(); public List<float> vector { get; set; }
bValue = reader.ReadBoolean(); public List<List<float>> Grid { get; set; }
var vectorCount = reader.ReadInt32();
if (vectorCount > 0) public void DeSerialize(BinaryReader reader)
{ {
vector = new List<float>(); Id = reader.ReadInt32();
for (int i = 0; i < vectorCount; i++) gender = reader.ReadString();
{ age = reader.ReadSingle();
vector.Add(reader.ReadSingle()); bValue = reader.ReadBoolean();
} var vectorCount = reader.ReadInt32();
} if (vectorCount > 0)
else {
{ vector = new List<float>();
vector = null; for (int i = 0; i < vectorCount; i++)
} {
var GridCount = reader.ReadInt32(); vector.Add(reader.ReadSingle());
if (GridCount > 0) }
{ }
Grid = new List<List<float>>(); else
for (int i = 0; i < GridCount; i++) {
{ vector = null;
var tempList = new List<float>(); }
var tempListCount = reader.ReadInt32(); var GridCount = reader.ReadInt32();
for (int j = 0; j < tempListCount; j++) if (GridCount > 0)
{ {
tempList.Add(reader.ReadSingle()); Grid = new List<List<float>>();
} for (int i = 0; i < GridCount; i++)
Grid.Add(tempList); {
} var tempList = new List<float>();
} var tempListCount = reader.ReadInt32();
else for (int j = 0; j < tempListCount; j++)
{ {
Grid = null; tempList.Add(reader.ReadSingle());
} }
} Grid.Add(tempList);
}
public void Serialize(BinaryWriter writer) }
{ else
writer.Write(Id); {
writer.Write(gender); Grid = null;
writer.Write(age); }
writer.Write(bValue); }
if (vector == null || vector.Count == 0)
{ public void Serialize(BinaryWriter writer)
writer.Write(0); {
} writer.Write(Id);
else writer.Write(gender);
{ writer.Write(age);
writer.Write(vector.Count); writer.Write(bValue);
for (int i = 0; i < vector.Count; i++) if (vector == null || vector.Count == 0)
{ {
writer.Write(vector[i]); writer.Write(0);
} }
} else
if (Grid == null || Grid.Count == 0) {
{ writer.Write(vector.Count);
writer.Write(0); for (int i = 0; i < vector.Count; i++)
} {
else writer.Write(vector[i]);
{ }
writer.Write(Grid.Count); }
for (int i = 0; i < Grid.Count; i++) if (Grid == null || Grid.Count == 0)
{ {
writer.Write(Grid[i].Count); writer.Write(0);
for (int j = 0; j < Grid[i].Count; j++) }
{ else
writer.Write(Grid[i][j]); {
} writer.Write(Grid.Count);
} for (int i = 0; i < Grid.Count; i++)
} {
} writer.Write(Grid[i].Count);
public override string ToString() for (int j = 0; j < Grid[i].Count; j++)
{ {
var str = $"Id:{Id} Gender:{gender} age:{age} bValue:{bValue} "; writer.Write(Grid[i][j]);
if (vector != null) }
{ }
str += $"vector:[{vector[0]},{vector[1]},{vector[2]}] "; }
} }
if (Grid != null) public override string ToString()
{ {
str += "Grid:["; var str = $"Id:{Id} Gender:{gender} age:{age} bValue:{bValue} ";
for (int i = 0; i < Grid.Count; i++) if (vector != null)
{ {
str += $"[{Grid[i][0]},{Grid[i][1]},{Grid[i][2]}]"; str += $"vector:[{vector[0]},{vector[1]},{vector[2]}] ";
if (i < Grid.Count - 1) }
str += ","; if (Grid != null)
} {
str += "]"; str += "Grid:[";
} for (int i = 0; i < Grid.Count; i++)
return str; {
} str += $"[{Grid[i][0]},{Grid[i][1]},{Grid[i][2]}]";
} if (i < Grid.Count - 1)
str += ",";
[Serializable] }
public partial class avatarguideTestConfig : IBinarySerializable str += "]";
{ }
public List<avatarguideTest> avatarguideTestInfos = new List<avatarguideTest>(); return str;
public void DeSerialize(BinaryReader reader) }
{ }
int count = reader.ReadInt32();
for (int i = 0;i < count; i++) [Serializable]
{ public partial class avatarguideTestConfig : IBinarySerializable
avatarguideTest tempData = new avatarguideTest(); {
tempData.DeSerialize(reader); public List<avatarguideTest> avatarguideTestInfos = new List<avatarguideTest>();
avatarguideTestInfos.Add(tempData); public void DeSerialize(BinaryReader reader)
} {
} int count = reader.ReadInt32();
for (int i = 0;i < count; i++)
public void Serialize(BinaryWriter writer) {
{ avatarguideTest tempData = new avatarguideTest();
writer.Write(avatarguideTestInfos.Count); tempData.DeSerialize(reader);
for (int i = 0; i < avatarguideTestInfos.Count; i++) avatarguideTestInfos.Add(tempData);
{ }
avatarguideTestInfos[i].Serialize(writer); }
}
} public void Serialize(BinaryWriter writer)
{
public IEnumerable<avatarguideTest> QueryById(int id) writer.Write(avatarguideTestInfos.Count);
{ for (int i = 0; i < avatarguideTestInfos.Count; i++)
var datas = from d in avatarguideTestInfos {
where d.Id == id avatarguideTestInfos[i].Serialize(writer);
select d; }
return datas; }
}
public IEnumerable<avatarguideTest> QueryById(int id)
public override string ToString() {
{ var datas = from d in avatarguideTestInfos
StringBuilder sb = new StringBuilder(); where d.Id == id
for (int i = 0; i < avatarguideTestInfos.Count; i++) select d;
{ return datas;
sb.Append($"{avatarguideTestInfos[i].ToString()}\n"); }
}
return sb.ToString(); public override string ToString()
} {
} StringBuilder sb = new StringBuilder();
``` for (int i = 0; i < avatarguideTestInfos.Count; i++)
{
#### 使用案例 sb.Append($"{avatarguideTestInfos[i].ToString()}\n");
##### 解析二进制文件 }
``` return sb.ToString();
IBinarySerializable newavList = new avatarguideTestList(); }
var readOK = FileManager.ReadBinaryDataFromFile(Path.Combine(path, "avatarguideTest.dat"), ref newavList); }
if (readOK) ```
{
ConsoleHelper.WriteInfoLine(newavList.ToString()); #### 使用案例
}
else ##### 解析二进制文件
{
ConsoleHelper.WriteErrorLine("读取失败"); ```
} IBinarySerializable newavList = new avatarguideTestList();
``` var readOK = FileManager.ReadBinaryDataFromFile(Path.Combine(path, "avatarguideTest.dat"), ref newavList);
![](img/3.jpg) if (readOK)
{
##### Unity解析二进制 ConsoleHelper.WriteInfoLine(newavList.ToString());
将二进制文件(后缀必须是.bytes)放在Resources目录,然后通过Resources.Load接口加载 }
``` else
var bytes = Resources.Load<TextAsset>("avatarguideTest"); {
if (bytes == null) ConsoleHelper.WriteErrorLine("读取失败");
{ }
return; ```
}
IBinarySerializable newavList = new avatarguideTestConfig(); ![](img/3.jpg)
var readOK = FileManager.ReadBinaryDataFromBytes(bytes.bytes, ref newavList);
if (readOK) ##### Unity解析二进制
{
Debug.Log(newavList.ToString()); 将二进制文件(后缀必须是.bytes)放在Resources目录,然后通过Resources.Load接口加载
//根据Id查询数据 ```
//var avatarguideTest = (avatarguideTestConfig)newavList; var bytes = Resources.Load<TextAsset>("avatarguideTest");
//var obj = avatarguideTest.QueryById(2); if (bytes == null)
//if (obj != null && obj.Count() > 0) {
// Debug.Log(obj.FirstOrDefault().ToString()); return;
} }
else IBinarySerializable newavList = new avatarguideTestConfig();
{ var readOK = FileManager.ReadBinaryDataFromBytes(bytes.bytes, ref newavList);
Debug.LogError("数据读取错误"); if (readOK)
} {
``` Debug.Log(newavList.ToString());
#### 泛型读表 //根据Id查询数据
``` //var avatarguideTest = (avatarguideTestConfig)newavList;
T ReadTable<T>(string tableName) where T : IBinarySerializable, new() //var obj = avatarguideTest.QueryById(2);
{ //if (obj != null && obj.Count() > 0)
var bytes = LoadTextAsset(tableName); // Debug.Log(obj.FirstOrDefault().ToString());
if (bytes != null) }
{ else
IBinarySerializable data = new T(); {
var readOK = FileManager.ReadBinaryDataFromBytes(bytes.bytes, ref data); Debug.LogError("数据读取错误");
if (readOK) }
{ ```
return (T)data;
} #### 泛型读表
else
{ ```
Debug.LogError($"{tableName}解析出错 类型{typeof(T)}"); T ReadTable<T>(string tableName) where T : IBinarySerializable, new()
} {
} var bytes = LoadTextAsset(tableName);
return default(T); if (bytes != null)
} {
``` IBinarySerializable data = new T();
##### 查询数据 var readOK = FileManager.ReadBinaryDataFromBytes(bytes.bytes, ref data);
``` if (readOK)
var avatarguideTest = (avatarguideTestConfig)newavList; {
var obj = avatarguideTest.QueryById(2); return (T)data;
if (obj != null && obj.Count() > 0) }
ConsoleHelper.WriteInfoLine(obj.FirstOrDefault().ToString()); else
``` {
Debug.LogError($"{tableName}解析出错 类型{typeof(T)}");
#### 自动化拷贝批处理 }
``` }
@echo off return default(T);
}
echo "开始拷贝jsons" ```
for %%i in (*.dat) do (
echo begin copy... %%i ##### 查询数据
copy /y %%~nxi ..\..\hola_unity\Assets\Resources\Config\%%~nxi
echo copy complate ... %%i ```
) var avatarguideTest = (avatarguideTestConfig)newavList;
echo "拷贝完成" var obj = avatarguideTest.QueryById(2);
if (obj != null && obj.Count() > 0)
pause ConsoleHelper.WriteInfoLine(obj.FirstOrDefault().ToString());
``` ```
#### 扩展类方法 #### 自动化拷贝批处理
上面的config类采用的是partical class 就是为了方便扩展自定义的方法,如果想要添加自定义方法也定义一个partical class文件作为扩展即可
```
#### 待扩展的功能 @echo off
目前还不是最理想的状态,还有很多可以扩展完善的功能,如下:
echo "开始拷贝jsons"
* 支持生成各种类型的文件,例如json、xml、proto、lua等 for %%i in (*.dat) do (
* 支持生成各种语法的模板代码 echo begin copy... %%i
* 支持Excel数据配置规范性检测,例如手误配置不符合规范导致加载异常,例如大小写逗号(肉眼容易忽略),或者空格等等 copy /y %%~nxi ..\..\hola_unity\Assets\Resources\Config\%%~nxi
* 支持Excel字段客户端服务器可选项 echo copy complate ... %%i
* 支持更多自定义数据类型扩展 )
* 支持枚举类型 echo "拷贝完成"
#### 代码 pause
https://github.com/dingxiaowei/ExcelTool 喜欢麻烦点个star吧 ```
#### Unity客户端使用范例 #### 扩展类方法
采用的美术效果机型适配商业化解决方案Demo
https://github.com/dingxiaowei/DeviceGrading 上面的config类采用的是partical class 就是为了方便扩展自定义的方法,如果想要添加自定义方法也定义一个partical class文件作为扩展即可
优雅的表格使用范本
#### 待扩展的功能
目前还不是最理想的状态,还有很多可以扩展完善的功能,如下:
* 支持生成各种类型的文件,例如json、xml、proto、lua等
* 支持生成各种语法的模板代码
* 支持Excel数据配置规范性检测,例如手误配置不符合规范导致加载异常,例如大小写逗号(肉眼容易忽略),或者空格等等
* 支持Excel字段客户端服务器可选项
* 支持更多自定义数据类型扩展
* 支持枚举类型
#### 代码
https://github.com/dingxiaowei/ExcelTool 喜欢麻烦点个star吧
#### Unity客户端使用范例
采用的美术效果机型适配商业化解决方案Demo
https://github.com/dingxiaowei/DeviceGrading
优雅的表格使用范本
todo: