fb7beedbad
- Add GenAudioConsts.cs to generate AudioConsts.cs with Cues, NameDictionaries, and Parameters - Remove GenEnums.cs and its enum generation functions - Update GenModels.cs to remove AudioObjectDefinitions generation - Modify ExcelHelper.cs to improve numeric and formula cell handling - Update Program.cs to use GenAudioConsts for audio constants generation - Update README.md with improved validation checks and CueSheet generation status
303 lines
7.2 KiB
Markdown
303 lines
7.2 KiB
Markdown
# ExcelTool
|
||
|
||
本项目基于 https://github.com/dingxiaowei/ExcelTool 开发。用于 [AudioSystem](https://github.com/htw128/UnityAudioExtend), [HapticSystem](https://github.com/htw128/UnityAudioExtend#Haptic) 导出数据使用。
|
||
|
||
#### 功能
|
||
|
||
* 生成对应的数据模板代码
|
||
* 支持生成模板代码字段注释
|
||
* 生成二进制文件
|
||
* 自动将文件拷贝到对应的工程目录
|
||
* 二进制数据读取
|
||
* 字段不配置会使用默认数值
|
||
|
||
#### 目前支持的字段
|
||
|
||
* 常规的字段,例如int,float,string,bool,long,list,intlist,longlist,floatlist,boollist,List<T> 大小写不限
|
||
* 支持自定义字段 vector,例如[1,2,3]
|
||
* 支持自定义字段 list,其实是vector数组,例如[[1,2,3],[2,3,4],[4,5,6]]
|
||
|
||
##### 自动生成的模板代码
|
||
|
||
```c#
|
||
/*
|
||
* auto generated by tools(注意:千万不要手动修改本文件)
|
||
* avatarguideTest
|
||
*/
|
||
using System;
|
||
using System.IO;
|
||
using System.Collections.Generic;
|
||
using System.Text;
|
||
using System.Linq;
|
||
|
||
[Serializable]
|
||
public class avatarguideTest : IBinarySerializable
|
||
{
|
||
public int Id { get; set; }
|
||
public string gender { get; set; }
|
||
public float age { get; set; }
|
||
public bool bValue { get; set; }
|
||
public List<float> vector { get; set; }
|
||
public List<List<float>> Grid { get; set; }
|
||
|
||
public void DeSerialize(BinaryReader reader)
|
||
{
|
||
Id = reader.ReadInt32();
|
||
gender = reader.ReadString();
|
||
age = reader.ReadSingle();
|
||
bValue = reader.ReadBoolean();
|
||
var vectorCount = reader.ReadInt32();
|
||
if (vectorCount > 0)
|
||
{
|
||
vector = new List<float>();
|
||
for (int i = 0; i < vectorCount; i++)
|
||
{
|
||
vector.Add(reader.ReadSingle());
|
||
}
|
||
}
|
||
else
|
||
{
|
||
vector = null;
|
||
}
|
||
var GridCount = reader.ReadInt32();
|
||
if (GridCount > 0)
|
||
{
|
||
Grid = new List<List<float>>();
|
||
for (int i = 0; i < GridCount; i++)
|
||
{
|
||
var tempList = new List<float>();
|
||
var tempListCount = reader.ReadInt32();
|
||
for (int j = 0; j < tempListCount; j++)
|
||
{
|
||
tempList.Add(reader.ReadSingle());
|
||
}
|
||
Grid.Add(tempList);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Grid = null;
|
||
}
|
||
}
|
||
|
||
public void Serialize(BinaryWriter writer)
|
||
{
|
||
writer.Write(Id);
|
||
writer.Write(gender);
|
||
writer.Write(age);
|
||
writer.Write(bValue);
|
||
if (vector == null || vector.Count == 0)
|
||
{
|
||
writer.Write(0);
|
||
}
|
||
else
|
||
{
|
||
writer.Write(vector.Count);
|
||
for (int i = 0; i < vector.Count; i++)
|
||
{
|
||
writer.Write(vector[i]);
|
||
}
|
||
}
|
||
if (Grid == null || Grid.Count == 0)
|
||
{
|
||
writer.Write(0);
|
||
}
|
||
else
|
||
{
|
||
writer.Write(Grid.Count);
|
||
for (int i = 0; i < Grid.Count; i++)
|
||
{
|
||
writer.Write(Grid[i].Count);
|
||
for (int j = 0; j < Grid[i].Count; j++)
|
||
{
|
||
writer.Write(Grid[i][j]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
public override string ToString()
|
||
{
|
||
var str = $"Id:{Id} Gender:{gender} age:{age} bValue:{bValue} ";
|
||
if (vector != null)
|
||
{
|
||
str += $"vector:[{vector[0]},{vector[1]},{vector[2]}] ";
|
||
}
|
||
if (Grid != null)
|
||
{
|
||
str += "Grid:[";
|
||
for (int i = 0; i < Grid.Count; i++)
|
||
{
|
||
str += $"[{Grid[i][0]},{Grid[i][1]},{Grid[i][2]}]";
|
||
if (i < Grid.Count - 1)
|
||
str += ",";
|
||
}
|
||
str += "]";
|
||
}
|
||
return str;
|
||
}
|
||
}
|
||
|
||
[Serializable]
|
||
public partial class avatarguideTestConfig : IBinarySerializable
|
||
{
|
||
public List<avatarguideTest> avatarguideTestInfos = new List<avatarguideTest>();
|
||
public void DeSerialize(BinaryReader reader)
|
||
{
|
||
int count = reader.ReadInt32();
|
||
for (int i = 0;i < count; i++)
|
||
{
|
||
avatarguideTest tempData = new avatarguideTest();
|
||
tempData.DeSerialize(reader);
|
||
avatarguideTestInfos.Add(tempData);
|
||
}
|
||
}
|
||
|
||
public void Serialize(BinaryWriter writer)
|
||
{
|
||
writer.Write(avatarguideTestInfos.Count);
|
||
for (int i = 0; i < avatarguideTestInfos.Count; i++)
|
||
{
|
||
avatarguideTestInfos[i].Serialize(writer);
|
||
}
|
||
}
|
||
|
||
public IEnumerable<avatarguideTest> QueryById(int id)
|
||
{
|
||
var datas = from d in avatarguideTestInfos
|
||
where d.Id == id
|
||
select d;
|
||
return datas;
|
||
}
|
||
|
||
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();
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 使用案例
|
||
|
||
##### 解析二进制文件
|
||
|
||
```c#
|
||
IBinarySerializable newavList = new avatarguideTestList();
|
||
var readOK = FileManager.ReadBinaryDataFromFile(Path.Combine(path, "avatarguideTest.dat"), ref newavList);
|
||
if (readOK)
|
||
{
|
||
ConsoleHelper.WriteInfoLine(newavList.ToString());
|
||
}
|
||
else
|
||
{
|
||
ConsoleHelper.WriteErrorLine("读取失败");
|
||
}
|
||
```
|
||
|
||

|
||
|
||
##### Unity解析二进制
|
||
|
||
将二进制文件(后缀必须是.bytes)放在Resources目录,然后通过Resources.Load接口加载
|
||
|
||
```c#
|
||
var bytes = Resources.Load<TextAsset>("avatarguideTest");
|
||
if (bytes == null)
|
||
{
|
||
return;
|
||
}
|
||
IBinarySerializable newavList = new avatarguideTestConfig();
|
||
var readOK = FileManager.ReadBinaryDataFromBytes(bytes.bytes, ref newavList);
|
||
if (readOK)
|
||
{
|
||
Debug.Log(newavList.ToString());
|
||
|
||
//根据Id查询数据
|
||
//var avatarguideTest = (avatarguideTestConfig)newavList;
|
||
//var obj = avatarguideTest.QueryById(2);
|
||
//if (obj != null && obj.Count() > 0)
|
||
// Debug.Log(obj.FirstOrDefault().ToString());
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("数据读取错误");
|
||
}
|
||
```
|
||
|
||
#### 泛型读表
|
||
|
||
```c#
|
||
T ReadTable<T>(string tableName) where T : IBinarySerializable, new()
|
||
{
|
||
var bytes = LoadTextAsset(tableName);
|
||
if (bytes != null)
|
||
{
|
||
IBinarySerializable data = new T();
|
||
var readOK = FileManager.ReadBinaryDataFromBytes(bytes.bytes, ref data);
|
||
if (readOK)
|
||
{
|
||
return (T)data;
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError($"{tableName}解析出错 类型{typeof(T)}");
|
||
}
|
||
}
|
||
return default(T);
|
||
}
|
||
```
|
||
|
||
##### 查询数据
|
||
|
||
```c#
|
||
var avatarguideTest = (avatarguideTestConfig)newavList;
|
||
var obj = avatarguideTest.QueryById(2);
|
||
if (obj != null && obj.Count() > 0)
|
||
ConsoleHelper.WriteInfoLine(obj.FirstOrDefault().ToString());
|
||
```
|
||
|
||
#### 自动化拷贝批处理
|
||
|
||
```batch
|
||
@echo off
|
||
|
||
echo "开始拷贝jsons"
|
||
for %%i in (*.dat) do (
|
||
echo begin copy... %%i
|
||
copy /y %%~nxi ..\..\hola_unity\Assets\Resources\Config\%%~nxi
|
||
echo copy complate ... %%i
|
||
)
|
||
echo "拷贝完成"
|
||
|
||
pause
|
||
```
|
||
|
||
#### 扩展类方法
|
||
|
||
上面的config类采用的是partical class 就是为了方便扩展自定义的方法,如果想要添加自定义方法也定义一个partical class文件作为扩展即可
|
||
|
||
#### TODO
|
||
|
||
* [x] 支持枚举类型
|
||
* [x] 支持不同表不同namespace
|
||
* [ ] 支持Excel数据配置规范性检测,例如手误配置不符合规范导致加载异常,例如大小写逗号(肉眼容易忽略),或者空格等等
|
||
* [ ] ID不能重复 给出错误
|
||
* [ ] Music、Audio Container不能自引用 给出错误
|
||
* [ ] 同时播放的音乐BPM必须一致 给出错误
|
||
* [ ] CueName不能包含空格` `,和`-`,不能以数字开头。给出警告
|
||
* [ ] Blend容器不能配置Haptic ID 给出警告
|
||
* [ ] SyncPoint功能性需要两个文件BPM、采样率皆一致。给出警告
|
||
* [x] 生成CueSheet避免magic number
|
||
* [ ] AudioObject支持Container嵌套
|
||
|
||
#### Unity客户端使用范例
|
||
|
||
采用的美术效果机型适配商业化解决方案Demo
|
||
https://github.com/dingxiaowei/DeviceGrading
|
||
优雅的表格使用范本
|
||
|