diff --git a/DungeonShooting_ExcelTool/DungeonShooting_ExcelTool.csproj b/DungeonShooting_ExcelTool/DungeonShooting_ExcelTool.csproj
index b27240e..9a963c3 100644
--- a/DungeonShooting_ExcelTool/DungeonShooting_ExcelTool.csproj
+++ b/DungeonShooting_ExcelTool/DungeonShooting_ExcelTool.csproj
@@ -15,6 +15,9 @@
PreserveNewest
+
+ PreserveNewest
+
diff --git a/DungeonShooting_ExcelTool/ExcelGenerator.cs b/DungeonShooting_ExcelTool/ExcelGenerator.cs
index 89a4165..2c96016 100644
--- a/DungeonShooting_ExcelTool/ExcelGenerator.cs
+++ b/DungeonShooting_ExcelTool/ExcelGenerator.cs
@@ -12,16 +12,44 @@
#else
private const string ExcelFilePath = "excel/excelFile";
#endif
+
+ private static HashSet _excelNames = new HashSet();
+
+
+ private enum CollectionsType
+ {
+ None,
+ Array,
+ Map
+ }
private class MappingData
{
+
public string TypeStr;
public string TypeName;
+ public CollectionsType CollectionsType;
+
+ public bool IsRefExcel;
+ public string RefTypeStr;
+ public string RefTypeName;
- public MappingData(string typeStr, string typeName)
+ public MappingData(string typeStr, string typeName, CollectionsType collectionsType)
{
TypeStr = typeStr;
TypeName = typeName;
+ CollectionsType = collectionsType;
+ IsRefExcel = false;
+ }
+
+ public MappingData(string typeStr, string typeName, CollectionsType collectionsType, string refTypeStr, string refTypeName)
+ {
+ TypeStr = typeStr;
+ TypeName = typeName;
+ CollectionsType = collectionsType;
+ IsRefExcel = true;
+ RefTypeStr = refTypeStr;
+ RefTypeName = refTypeName;
}
}
@@ -46,6 +74,13 @@
if (directoryInfo.Exists)
{
var fileInfos = directoryInfo.GetFiles();
+ //记录文件
+ foreach (var fileInfo in fileInfos)
+ {
+ var fileName = Path.GetFileNameWithoutExtension(fileInfo.Name).FirstToUpper();
+ _excelNames.Add(fileName);
+ }
+ //读取配置文件
foreach (var fileInfo in fileInfos)
{
if (fileInfo.Extension == ".xlsx")
@@ -113,13 +148,49 @@
var fieldCode = "";
var callFuncCode = "";
+ var callInitRefFuncCode = "";
var funcCode = "";
+ var initRefFuncCode = "";
foreach (var excelData in excelList)
{
var idName = excelData.ColumnNames[0];
var idTypeStr = excelData.ColumnMappingData[idName].TypeStr;
+ //---------------------------- 引用其他表处理 ----------------------------
+ var hasRefColumn = false;
+ var refColumnNoneCode = "";
+ foreach (var columnName in excelData.ColumnNames)
+ {
+ var mappingData = excelData.ColumnMappingData[columnName];
+ if (mappingData.IsRefExcel)
+ {
+ hasRefColumn = true;
+ if (mappingData.CollectionsType == CollectionsType.None)
+ {
+ refColumnNoneCode += $" item.{columnName} = {mappingData.RefTypeName}_Map[item.__{columnName}];\n";
+ }
+ else if (mappingData.CollectionsType == CollectionsType.Array)
+ {
+ refColumnNoneCode += $" item.{columnName} = new {mappingData.RefTypeName}[item.__{columnName}.Length];\n";
+ refColumnNoneCode += $" for (var i = 0; i < item.__{columnName}.Length; i++)\n";
+ refColumnNoneCode += $" {{\n";
+ refColumnNoneCode += $" item.{columnName}[i] = {mappingData.RefTypeName}_Map[item.__{columnName}[i]];\n";
+ refColumnNoneCode += $" }}\n";
+ }
+ else
+ {
+ refColumnNoneCode += $" item.{columnName} = new {mappingData.RefTypeStr}();\n";
+ refColumnNoneCode += $" foreach (var pair in item.__{columnName})\n";
+ refColumnNoneCode += $" {{\n";
+ refColumnNoneCode += $" item.{columnName}.Add(pair.Key, {mappingData.RefTypeName}_Map[pair.Value]);\n";
+ refColumnNoneCode += $" }}\n";
+ }
+ refColumnNoneCode += $"\n";
+ }
+ }
+
+ //----------------------------- 数据集合 ------------------------------------
fieldCode += $" /// \n";
fieldCode += $" /// {excelData.TableName}.xlsx表数据集合, 以 List 形式存储, 数据顺序与 Excel 表相同\n";
fieldCode += $" /// \n";
@@ -130,6 +201,7 @@
fieldCode += $" public static Dictionary<{idTypeStr}, {excelData.TableName}> {excelData.TableName}_Map {{ get; private set; }}\n";
fieldCode += $"\n";
+ //------------------------------- 初始化函数 -------------------------------------
callFuncCode += $" _Init{excelData.TableName}Config();\n";
funcCode += $" private static void _Init{excelData.TableName}Config()\n";
@@ -137,7 +209,14 @@
funcCode += $" try\n";
funcCode += $" {{\n";
funcCode += $" var text = _ReadConfigAsText(\"res://resource/config/{excelData.TableName}.json\");\n";
- funcCode += $" {excelData.TableName}_List = JsonSerializer.Deserialize>(text);\n";
+ if (hasRefColumn) //存在引用列
+ {
+ funcCode += $" {excelData.TableName}_List = new List<{excelData.TableName}>(JsonSerializer.Deserialize>(text));\n";
+ }
+ else
+ {
+ funcCode += $" {excelData.TableName}_List = JsonSerializer.Deserialize>(text);\n";
+ }
funcCode += $" {excelData.TableName}_Map = new Dictionary<{idTypeStr}, {excelData.TableName}>();\n";
funcCode += $" foreach (var item in {excelData.TableName}_List)\n";
funcCode += $" {{\n";
@@ -150,6 +229,29 @@
funcCode += $" throw new Exception(\"初始化表'{excelData.TableName}'失败!\");\n";
funcCode += $" }}\n";
funcCode += $" }}\n";
+
+
+ //------------------------------- 初始化引用 ---------------------------------
+ if (hasRefColumn)
+ {
+ callInitRefFuncCode += $" _Init{excelData.TableName}Ref();\n";
+
+ initRefFuncCode += $" private static void _Init{excelData.TableName}Ref()\n";
+ initRefFuncCode += $" {{\n";
+ initRefFuncCode += $" foreach (Ref_{excelData.TableName} item in {excelData.TableName}_List)\n";
+ initRefFuncCode += $" {{\n";
+ initRefFuncCode += $" try\n";
+ initRefFuncCode += $" {{\n";
+ initRefFuncCode += refColumnNoneCode;
+ initRefFuncCode += $" }}\n";
+ initRefFuncCode += $" catch (Exception e)\n";
+ initRefFuncCode += $" {{\n";
+ initRefFuncCode += $" GD.PrintErr(e.ToString());\n";
+ initRefFuncCode += $" throw new Exception(\"初始化'{excelData.TableName}'引用其他表数据失败, 当前行id: \" + item.Id);\n";
+ initRefFuncCode += $" }}\n";
+ initRefFuncCode += $" }}\n";
+ initRefFuncCode += $" }}\n";
+ }
}
code += fieldCode;
@@ -164,8 +266,12 @@
code += $" _init = true;\n";
code += $"\n";
code += callFuncCode;
+ code += $"\n";
+ code += callInitRefFuncCode;
code += $" }}\n";
code += funcCode;
+ code += $"\n";
+ code += initRefFuncCode;
code += $" private static string _ReadConfigAsText(string path)\n";
code += $" {{\n";
code += $" var file = FileAccess.Open(path, FileAccess.ModeFlags.Read);\n";
@@ -190,7 +296,9 @@
outStr += $"public static partial class ExcelConfig\n{{\n";
outStr += $" public class {fileName}\n";
outStr += $" {{\n";
-
+ //继承的带有引用其他表的类代码
+ var outRefStr = "";
+
var cloneFuncStr = $" /// \n";
cloneFuncStr += $" /// 返回浅拷贝出的新对象\n";
cloneFuncStr += $" /// \n";
@@ -274,8 +382,26 @@
outStr += $" /// \n";
outStr += $" /// {description}\n";
outStr += $" /// \n";
- outStr += $" [JsonInclude]\n";
- outStr += $" public {mappingData.TypeStr} {field};\n\n";
+ if (!mappingData.IsRefExcel) //没有引用其他表
+ {
+ outStr += $" [JsonInclude]\n";
+ outStr += $" public {mappingData.TypeStr} {field};\n\n";
+ }
+ else
+ {
+ outStr += $" public {mappingData.RefTypeStr} {field};\n\n";
+ }
+
+ if (mappingData.IsRefExcel) //引用其他表
+ {
+ if (string.IsNullOrEmpty(outRefStr))
+ {
+ outRefStr += $" private class Ref_{fileName} : {fileName}\n";
+ outRefStr += $" {{\n";
+ }
+ outRefStr += $" [JsonInclude]\n";
+ outRefStr += $" public {mappingData.TypeStr} __{field};\n\n";
+ }
cloneFuncStr += $" inst.{field} = {field};\n";
}
@@ -284,6 +410,13 @@
cloneFuncStr += " }\n";
outStr += cloneFuncStr;
outStr += " }\n";
+
+ if (!string.IsNullOrEmpty(outRefStr))
+ {
+ outRefStr += " }\n";
+ outStr += outRefStr;
+ }
+
outStr += "}";
//解析字段类型
@@ -324,57 +457,58 @@
var fieldName = excelData.ColumnNames[j];
var mappingData = excelData.ColumnMappingData[fieldName];
+ var field = mappingData.IsRefExcel ? "__" + fieldName : fieldName;
try
{
switch (mappingData.TypeStr)
{
case "bool":
case "boolean":
- data.Add(fieldName, GetCellBooleanValue(cell));
+ data.Add(field, GetCellBooleanValue(cell));
break;
case "byte":
- data.Add(fieldName, Convert.ToByte(GetCellNumberValue(cell)));
+ data.Add(field, Convert.ToByte(GetCellNumberValue(cell)));
break;
case "sbyte":
- data.Add(fieldName, Convert.ToSByte(GetCellNumberValue(cell)));
+ data.Add(field, Convert.ToSByte(GetCellNumberValue(cell)));
break;
case "short":
- data.Add(fieldName, Convert.ToInt16(GetCellNumberValue(cell)));
+ data.Add(field, Convert.ToInt16(GetCellNumberValue(cell)));
break;
case "ushort":
- data.Add(fieldName, Convert.ToUInt16(GetCellNumberValue(cell)));
+ data.Add(field, Convert.ToUInt16(GetCellNumberValue(cell)));
break;
case "int":
- data.Add(fieldName, Convert.ToInt32(GetCellNumberValue(cell)));
+ data.Add(field, Convert.ToInt32(GetCellNumberValue(cell)));
break;
case "uint":
- data.Add(fieldName, Convert.ToUInt32(GetCellNumberValue(cell)));
+ data.Add(field, Convert.ToUInt32(GetCellNumberValue(cell)));
break;
case "long":
- data.Add(fieldName, Convert.ToInt64(GetCellNumberValue(cell)));
+ data.Add(field, Convert.ToInt64(GetCellNumberValue(cell)));
break;
case "ulong":
- data.Add(fieldName, Convert.ToUInt64(GetCellNumberValue(cell)));
+ data.Add(field, Convert.ToUInt64(GetCellNumberValue(cell)));
break;
case "float":
- data.Add(fieldName, Convert.ToSingle(GetCellNumberValue(cell)));
+ data.Add(field, Convert.ToSingle(GetCellNumberValue(cell)));
break;
case "double":
- data.Add(fieldName, GetCellNumberValue(cell));
+ data.Add(field, GetCellNumberValue(cell));
break;
case "string":
- data.Add(fieldName, GetCellStringValue(cell));
+ data.Add(field, GetCellStringValue(cell));
break;
default:
{
var cellStringValue = GetCellStringValue(cell);
if (cellStringValue.Length == 0)
{
- data.Add(fieldName, null);
+ data.Add(field, null);
}
else
{
- data.Add(fieldName, JsonSerializer.Deserialize(cellStringValue, excelData.ColumnType[fieldName]));
+ data.Add(field, JsonSerializer.Deserialize(cellStringValue, excelData.ColumnType[fieldName]));
}
}
break;
@@ -434,15 +568,30 @@
return cell.BooleanCellValue;
}
- private static MappingData ConvertToType(string str)
+ private static MappingData ConvertToType(string str, int depth = 0)
{
if (Regex.IsMatch(str, "^\\w+$"))
{
var typeStr = TypeStrMapping(str);
var typeName = TypeNameMapping(str);
- return new MappingData(typeStr, typeName);
+ return new MappingData(typeStr, typeName, CollectionsType.None);
}
- else if (str.StartsWith('{'))
+ else if (Regex.IsMatch(str, "^\\$\\w+$")) //引用其他表
+ {
+ var realName = str.Substring(1);
+ if (!_excelNames.Contains(realName))
+ {
+ throw new Exception($"引用表数据失败, 未找到表: {realName}!");
+ }
+
+ if (depth > 1)
+ {
+ throw new Exception("引用表数据失败, 引用表数据仅支持放入第一层的数组和字典!");
+ }
+
+ return new MappingData(TypeStrMapping("string"), TypeNameMapping("string"), CollectionsType.None, realName, realName);
+ }
+ else if (str.StartsWith('{')) //字典
{
var tempStr = str.Substring(1, str.Length - 2);
var index = tempStr.IndexOf(':');
@@ -456,19 +605,35 @@
{
throw new Exception($"字典key类型必须是基础类型!");
}
- var type1 = ConvertToType(keyStr);
- var type2 = ConvertToType(tempStr.Substring(index + 1));
+
+ var type1 = ConvertToType(keyStr, depth + 1);
+ var type2 = ConvertToType(tempStr.Substring(index + 1), depth + 1);
+
var typeStr = $"Dictionary<{type1.TypeStr}, {type2.TypeStr}>";
var typeName = $"System.Collections.Generic.Dictionary`2[[{type1.TypeName}],[{type2.TypeName}]]";
- return new MappingData(typeStr, typeName);
+
+ if (type2.IsRefExcel) //引用过其他表
+ {
+ var refTypeStr = $"Dictionary<{type1.TypeStr}, {type2.RefTypeStr}>";
+ return new MappingData(typeStr, typeName, CollectionsType.Map, refTypeStr, type2.RefTypeName);
+ }
+
+ return new MappingData(typeStr, typeName, CollectionsType.Map);
}
- else if (str.StartsWith('['))
+ else if (str.StartsWith('[')) //数组
{
var tempStr = str.Substring(1, str.Length - 2);
- var typeData = ConvertToType(tempStr);
+ var typeData = ConvertToType(tempStr, depth + 1);
var typeStr = typeData.TypeStr + "[]";
var typeName = typeData.TypeName + "[]";
- return new MappingData(typeStr, typeName);
+
+ if (typeData.IsRefExcel) //引用过其他表
+ {
+ var refTypeStr = typeData.RefTypeStr + "[]";
+ return new MappingData(typeStr, typeName, CollectionsType.Array, refTypeStr, typeData.RefTypeName);
+ }
+
+ return new MappingData(typeStr, typeName, CollectionsType.Array);
}
throw new Exception("类型描述语法错误!");
}
diff --git a/DungeonShooting_ExcelTool/excelFile/ActivityObject.xlsx b/DungeonShooting_ExcelTool/excelFile/ActivityObject.xlsx
new file mode 100644
index 0000000..b5ef62e
--- /dev/null
+++ b/DungeonShooting_ExcelTool/excelFile/ActivityObject.xlsx
Binary files differ
diff --git a/DungeonShooting_ExcelTool/excelFile/Role.xlsx b/DungeonShooting_ExcelTool/excelFile/Role.xlsx
deleted file mode 100644
index b062c08..0000000
--- a/DungeonShooting_ExcelTool/excelFile/Role.xlsx
+++ /dev/null
Binary files differ
diff --git a/DungeonShooting_ExcelTool/excelFile/Test.xlsx b/DungeonShooting_ExcelTool/excelFile/Test.xlsx
new file mode 100644
index 0000000..3699e31
--- /dev/null
+++ b/DungeonShooting_ExcelTool/excelFile/Test.xlsx
Binary files differ
diff --git a/DungeonShooting_ExcelTool/excelFile/Weapon.xlsx b/DungeonShooting_ExcelTool/excelFile/Weapon.xlsx
index 11248a8..bd6cc04 100644
--- a/DungeonShooting_ExcelTool/excelFile/Weapon.xlsx
+++ b/DungeonShooting_ExcelTool/excelFile/Weapon.xlsx
Binary files differ
diff --git a/DungeonShooting_ExcelTool/serialize/test/ExcelConfig.cs b/DungeonShooting_ExcelTool/serialize/test/ExcelConfig.cs
new file mode 100644
index 0000000..bdd2459
--- /dev/null
+++ b/DungeonShooting_ExcelTool/serialize/test/ExcelConfig.cs
@@ -0,0 +1,140 @@
+using System;
+using System.Collections.Generic;
+using System.Text.Json;
+//using Godot;
+
+namespace Config;
+
+public static partial class ExcelConfig
+{
+ ///
+ /// ActivityObject.xlsx表数据集合, 以 List 形式存储, 数据顺序与 Excel 表相同
+ ///
+ public static List ActivityObject_List { get; private set; }
+ ///
+ /// ActivityObject.xlsx表数据集合, 里 Map 形式存储, key 为 Id
+ ///
+ public static Dictionary ActivityObject_Map { get; private set; }
+
+ ///
+ /// Test.xlsx表数据集合, 以 List 形式存储, 数据顺序与 Excel 表相同
+ ///
+ public static List Test_List { get; private set; }
+ ///
+ /// Test.xlsx表数据集合, 里 Map 形式存储, key 为 Id
+ ///
+ public static Dictionary Test_Map { get; private set; }
+
+ ///
+ /// Weapon.xlsx表数据集合, 以 List 形式存储, 数据顺序与 Excel 表相同
+ ///
+ public static List Weapon_List { get; private set; }
+ ///
+ /// Weapon.xlsx表数据集合, 里 Map 形式存储, key 为 Id
+ ///
+ public static Dictionary Weapon_Map { get; private set; }
+
+
+ private static bool _init = false;
+ ///
+ /// 初始化所有配置表数据
+ ///
+ public static void Init()
+ {
+ if (_init) return;
+ _init = true;
+
+ _InitActivityObjectConfig();
+ _InitTestConfig();
+ _InitWeaponConfig();
+
+ _InitTestRef();
+ }
+ private static void _InitActivityObjectConfig()
+ {
+ try
+ {
+ var text = _ReadConfigAsText("res://resource/config/ActivityObject.json");
+ ActivityObject_List = JsonSerializer.Deserialize>(text);
+ ActivityObject_Map = new Dictionary();
+ foreach (var item in ActivityObject_List)
+ {
+ ActivityObject_Map.Add(item.Id, item);
+ }
+ }
+ catch (Exception e)
+ {
+ //GD.PrintErr(e.ToString());
+ throw new Exception("初始化表'ActivityObject'失败!");
+ }
+ }
+ private static void _InitTestConfig()
+ {
+ try
+ {
+ var text = _ReadConfigAsText("res://resource/config/Test.json");
+ Test_List = JsonSerializer.Deserialize>(text);
+ Test_Map = new Dictionary();
+ foreach (var item in Test_List)
+ {
+ Test_Map.Add(item.Id, item);
+ }
+ }
+ catch (Exception e)
+ {
+ //GD.PrintErr(e.ToString());
+ throw new Exception("初始化表'Test'失败!");
+ }
+ }
+ private static void _InitWeaponConfig()
+ {
+ try
+ {
+ var text = _ReadConfigAsText("res://resource/config/Weapon.json");
+ Weapon_List = JsonSerializer.Deserialize>(text);
+ Weapon_Map = new Dictionary();
+ foreach (var item in Weapon_List)
+ {
+ Weapon_Map.Add(item.Id, item);
+ }
+ }
+ catch (Exception e)
+ {
+ //GD.PrintErr(e.ToString());
+ throw new Exception("初始化表'Weapon'失败!");
+ }
+ }
+
+ private static void _InitTestRef()
+ {
+ foreach (var item in Test_List)
+ {
+ try
+ {
+ item.Weapon = Weapon_Map[item._Weapon];
+ item.ActivityObject = ActivityObject_Map[item._ActivityObject];
+
+ item.Weapons = new Weapon[item._Weapons.Length];
+ for (var i = 0; i < item._Weapons.Length; i++)
+ {
+ item.Weapons[i] = Weapon_Map[item._Weapons[i]];
+ }
+
+ item.WeaponMap = new Dictionary();
+ foreach (var pair in item._WeaponMap)
+ {
+ item.WeaponMap.Add(pair.Key, Weapon_Map[pair.Value]);
+ }
+ }
+ catch (Exception e)
+ {
+ //GD.PrintErr(e.ToString());
+ throw new Exception("初始化'Test'引用其他表数据失败, 当前行id: " + item.Id);
+ }
+ }
+ }
+ private static string _ReadConfigAsText(string path)
+ {
+ return "";
+ }
+}
\ No newline at end of file
diff --git a/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_ActivityObject.cs b/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_ActivityObject.cs
new file mode 100644
index 0000000..12e9730
--- /dev/null
+++ b/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_ActivityObject.cs
@@ -0,0 +1,55 @@
+using System.Text.Json.Serialization;
+using System.Collections.Generic;
+
+namespace Config;
+
+public static partial class ExcelConfig
+{
+ public class ActivityObject
+ {
+ ///
+ /// 物体唯一id
+ /// 需要添加类型前缀
+ ///
+ [JsonInclude]
+ public string Id;
+
+ ///
+ /// Test(测试对象): 2
+ /// Role(角色): 3
+ /// Enemy(敌人): 4
+ /// Weapon(武器): 5
+ /// Bullet(子弹): 6
+ /// Shell(弹壳): 7
+ /// Effect(特效): 8
+ /// Other(其它类型): 9
+ ///
+ [JsonInclude]
+ public int Type;
+
+ ///
+ /// 物体预制场景路径, 场景根节点必须是ActivityObject子类
+ ///
+ [JsonInclude]
+ public string Prefab;
+
+ ///
+ /// 物体备注
+ ///
+ [JsonInclude]
+ public string Remark;
+
+ ///
+ /// 返回浅拷贝出的新对象
+ ///
+ public ActivityObject Clone()
+ {
+ var inst = new ActivityObject();
+ inst.Id = Id;
+ inst.Type = Type;
+ inst.Prefab = Prefab;
+ inst.Remark = Remark;
+ return inst;
+ }
+ }
+}
\ No newline at end of file
diff --git a/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_Test.cs b/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_Test.cs
new file mode 100644
index 0000000..52ccb6f
--- /dev/null
+++ b/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_Test.cs
@@ -0,0 +1,58 @@
+using System.Text.Json.Serialization;
+using System.Collections.Generic;
+
+namespace Config;
+
+public static partial class ExcelConfig
+{
+ public class Test
+ {
+ ///
+ /// 唯一id
+ ///
+ [JsonInclude]
+ public string Id;
+
+ ///
+ /// 引用的武器数据
+ ///
+ public Weapon Weapon;
+ [JsonInclude]
+ public string _Weapon;
+
+ ///
+ /// 引用的武器数据(数组)
+ ///
+ public Weapon[] Weapons;
+ [JsonInclude]
+ public string[] _Weapons;
+
+ ///
+ /// 引用的武器数据(字典)
+ ///
+ public Dictionary WeaponMap;
+ [JsonInclude]
+ public Dictionary _WeaponMap;
+
+ ///
+ /// 引用ActivityObject
+ ///
+ public ActivityObject ActivityObject;
+ [JsonInclude]
+ public string _ActivityObject;
+
+ ///
+ /// 返回浅拷贝出的新对象
+ ///
+ public Test Clone()
+ {
+ var inst = new Test();
+ inst.Id = Id;
+ inst.Weapon = Weapon;
+ inst.Weapons = Weapons;
+ inst.WeaponMap = WeaponMap;
+ inst.ActivityObject = ActivityObject;
+ return inst;
+ }
+ }
+}
\ No newline at end of file
diff --git a/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_Weapon.cs b/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_Weapon.cs
new file mode 100644
index 0000000..a2953d8
--- /dev/null
+++ b/DungeonShooting_ExcelTool/serialize/test/ExcelConfig_Weapon.cs
@@ -0,0 +1,377 @@
+using System.Text.Json.Serialization;
+using System.Collections.Generic;
+
+namespace Config;
+
+public static partial class ExcelConfig
+{
+ public class Weapon
+ {
+ ///
+ /// 武器属性id
+ ///
+ [JsonInclude]
+ public string Id;
+
+ ///
+ /// 属性绑定武器的Id,如果是Ai使用的数据, 则填空字符串串
+ ///
+ [JsonInclude]
+ public string WeaponId;
+
+ ///
+ /// 武器显示的名称
+ ///
+ [JsonInclude]
+ public string Name;
+
+ ///
+ /// 武器的图标
+ ///
+ [JsonInclude]
+ public string Icon;
+
+ ///
+ /// 重量
+ ///
+ [JsonInclude]
+ public float Weight;
+
+ ///
+ /// 武器类型:
+ /// 1.副武器
+ /// 2.主武器
+ /// 3.重型武器
+ ///
+ [JsonInclude]
+ public byte WeightType;
+
+ ///
+ /// 是否连续发射, 如果为false, 则每次发射都需要扣动扳机
+ ///
+ [JsonInclude]
+ public bool ContinuousShoot;
+
+ ///
+ /// 弹夹容量
+ ///
+ [JsonInclude]
+ public int AmmoCapacity;
+
+ ///
+ /// 弹药容量上限
+ ///
+ [JsonInclude]
+ public int MaxAmmoCapacity;
+
+ ///
+ /// 默认起始备用弹药数量
+ ///
+ [JsonInclude]
+ public int StandbyAmmoCapacity;
+
+ ///
+ /// 装弹时间 (单位: 秒)
+ ///
+ [JsonInclude]
+ public float ReloadTime;
+
+ ///
+ /// 每粒子弹是否是单独装填, 如果是, 那么每上一发子弹的时间就是 ReloadTime, 可以做霰弹武器装填效果
+ ///
+ [JsonInclude]
+ public bool AloneReload;
+
+ ///
+ /// 单独装填时每次装填子弹数量, 必须要将 'AloneReload' 属性设置为 true
+ ///
+ [JsonInclude]
+ public int AloneReloadCount;
+
+ ///
+ /// 单独装填的子弹时可以立即射击, 必须要将 'AloneReload' 属性设置为 true
+ ///
+ [JsonInclude]
+ public bool AloneReloadCanShoot;
+
+ ///
+ /// 是否为松发开火, 也就是松开扳机才开火, 若要启用该属性, 必须将 'ContinuousShoot' 设置为 false
+ ///
+ [JsonInclude]
+ public bool LooseShoot;
+
+ ///
+ /// 最少需要蓄力多久才能开火, 必须将 'LooseShoot' 设置为 true
+ ///
+ [JsonInclude]
+ public float MinChargeTime;
+
+ ///
+ /// 连续发射最小次数, 仅当 ContinuousShoot 为 false 时生效
+ ///
+ [JsonInclude]
+ public int MinContinuousCount;
+
+ ///
+ /// 连续发射最大次数, 仅当 ContinuousShoot 为 false 时生效
+ ///
+ [JsonInclude]
+ public int MaxContinuousCount;
+
+ ///
+ /// 按下一次扳机后需要多长时间才能再次感应按下
+ ///
+ [JsonInclude]
+ public float TriggerInterval;
+
+ ///
+ /// 初始射速, 初始每分钟能开火次数
+ ///
+ [JsonInclude]
+ public float StartFiringSpeed;
+
+ ///
+ /// 最终射速, 最终每分钟能开火次数, 仅当 ContinuousShoot 为 true 时生效
+ ///
+ [JsonInclude]
+ public float FinalFiringSpeed;
+
+ ///
+ /// 按下扳机并开火后射速增加速率
+ ///
+ [JsonInclude]
+ public float FiringSpeedAddSpeed;
+
+ ///
+ /// 松开扳机后射速消散速率
+ ///
+ [JsonInclude]
+ public float FiringSpeedBackSpeed;
+
+ ///
+ /// 单次开火发射子弹最小数量
+ ///
+ [JsonInclude]
+ public int MinFireBulletCount;
+
+ ///
+ /// 单次开火发射子弹最大数量
+ ///
+ [JsonInclude]
+ public int MaxFireBulletCount;
+
+ ///
+ /// 开火前延时
+ ///
+ [JsonInclude]
+ public float DelayedTime;
+
+ ///
+ /// 初始散射半径
+ ///
+ [JsonInclude]
+ public float StartScatteringRange;
+
+ ///
+ /// 最终散射半径
+ ///
+ [JsonInclude]
+ public float FinalScatteringRange;
+
+ ///
+ /// 每次发射后散射增加值
+ ///
+ [JsonInclude]
+ public float ScatteringRangeAddValue;
+
+ ///
+ /// 松开扳机后散射销退速率
+ ///
+ [JsonInclude]
+ public float ScatteringRangeBackSpeed;
+
+ ///
+ /// 松开扳机多久后开始销退散射值 (单位: 秒)
+ ///
+ [JsonInclude]
+ public float ScatteringRangeBackTime;
+
+ ///
+ /// 子弹飞行最小距离
+ ///
+ [JsonInclude]
+ public float MinDistance;
+
+ ///
+ /// 子弹飞行最大距离
+ ///
+ [JsonInclude]
+ public float MaxDistance;
+
+ ///
+ /// 最小后坐力 (仅用于开火后武器身抖动)
+ ///
+ [JsonInclude]
+ public float MinBacklash;
+
+ ///
+ /// 最大后坐力 (仅用于开火后武器身抖动)
+ ///
+ [JsonInclude]
+ public float MaxBacklash;
+
+ ///
+ /// 后坐力偏移回归回归速度
+ ///
+ [JsonInclude]
+ public float BacklashRegressionSpeed;
+
+ ///
+ /// 开火后武器口上抬角度
+ ///
+ [JsonInclude]
+ public float UpliftAngle;
+
+ ///
+ /// 武器默认上抬角度
+ ///
+ [JsonInclude]
+ public float DefaultAngle;
+
+ ///
+ /// 开火后武器口角度恢复速度倍数
+ ///
+ [JsonInclude]
+ public float UpliftAngleRestore;
+
+ ///
+ /// 默认射出的子弹id
+ ///
+ [JsonInclude]
+ public string BulletId;
+
+ ///
+ /// 投抛状态下物体碰撞器大小
+ ///
+ [JsonInclude]
+ public SerializeVector2 ThrowCollisionSize;
+
+ ///
+ /// 射击音效
+ ///
+ [JsonInclude]
+ public string ShootSound;
+
+ ///
+ /// 换弹音效
+ ///
+ [JsonInclude]
+ public string ReloadSound;
+
+ ///
+ /// 换弹音效延时时间
+ ///
+ [JsonInclude]
+ public float ReloadSoundDelayTime;
+
+ ///
+ /// 上膛音效
+ ///
+ [JsonInclude]
+ public string EquipSound;
+
+ ///
+ /// 上膛音效延时时间
+ ///
+ [JsonInclude]
+ public float EquipSoundDelayTime;
+
+ ///
+ /// Ai属性
+ /// Ai 使用该武器时的武器数据, 设置该字段, 可让同一把武器在敌人和玩家手上有不同属性
+ /// 如果不填则Ai和玩家使用同一种属性
+ ///
+ [JsonInclude]
+ public string AiUseAttributeId;
+
+ ///
+ /// Ai属性
+ /// 目标锁定时间, 也就是瞄准目标多久才会开火, (单位: 秒)
+ ///
+ [JsonInclude]
+ public float AiTargetLockingTime;
+
+ ///
+ /// Ai属性
+ /// Ai使用该武器发射的子弹速度缩放比
+ ///
+ [JsonInclude]
+ public float AiBulletSpeedScale;
+
+ ///
+ /// Ai属性
+ /// Ai使用该武器消耗弹药的概率, (0 - 1)
+ ///
+ [JsonInclude]
+ public float AiAmmoConsumptionProbability;
+
+ ///
+ /// 返回浅拷贝出的新对象
+ ///
+ public Weapon Clone()
+ {
+ var inst = new Weapon();
+ inst.Id = Id;
+ inst.WeaponId = WeaponId;
+ inst.Name = Name;
+ inst.Icon = Icon;
+ inst.Weight = Weight;
+ inst.WeightType = WeightType;
+ inst.ContinuousShoot = ContinuousShoot;
+ inst.AmmoCapacity = AmmoCapacity;
+ inst.MaxAmmoCapacity = MaxAmmoCapacity;
+ inst.StandbyAmmoCapacity = StandbyAmmoCapacity;
+ inst.ReloadTime = ReloadTime;
+ inst.AloneReload = AloneReload;
+ inst.AloneReloadCount = AloneReloadCount;
+ inst.AloneReloadCanShoot = AloneReloadCanShoot;
+ inst.LooseShoot = LooseShoot;
+ inst.MinChargeTime = MinChargeTime;
+ inst.MinContinuousCount = MinContinuousCount;
+ inst.MaxContinuousCount = MaxContinuousCount;
+ inst.TriggerInterval = TriggerInterval;
+ inst.StartFiringSpeed = StartFiringSpeed;
+ inst.FinalFiringSpeed = FinalFiringSpeed;
+ inst.FiringSpeedAddSpeed = FiringSpeedAddSpeed;
+ inst.FiringSpeedBackSpeed = FiringSpeedBackSpeed;
+ inst.MinFireBulletCount = MinFireBulletCount;
+ inst.MaxFireBulletCount = MaxFireBulletCount;
+ inst.DelayedTime = DelayedTime;
+ inst.StartScatteringRange = StartScatteringRange;
+ inst.FinalScatteringRange = FinalScatteringRange;
+ inst.ScatteringRangeAddValue = ScatteringRangeAddValue;
+ inst.ScatteringRangeBackSpeed = ScatteringRangeBackSpeed;
+ inst.ScatteringRangeBackTime = ScatteringRangeBackTime;
+ inst.MinDistance = MinDistance;
+ inst.MaxDistance = MaxDistance;
+ inst.MinBacklash = MinBacklash;
+ inst.MaxBacklash = MaxBacklash;
+ inst.BacklashRegressionSpeed = BacklashRegressionSpeed;
+ inst.UpliftAngle = UpliftAngle;
+ inst.DefaultAngle = DefaultAngle;
+ inst.UpliftAngleRestore = UpliftAngleRestore;
+ inst.BulletId = BulletId;
+ inst.ThrowCollisionSize = ThrowCollisionSize;
+ inst.ShootSound = ShootSound;
+ inst.ReloadSound = ReloadSound;
+ inst.ReloadSoundDelayTime = ReloadSoundDelayTime;
+ inst.EquipSound = EquipSound;
+ inst.EquipSoundDelayTime = EquipSoundDelayTime;
+ inst.AiUseAttributeId = AiUseAttributeId;
+ inst.AiTargetLockingTime = AiTargetLockingTime;
+ inst.AiBulletSpeedScale = AiBulletSpeedScale;
+ inst.AiAmmoConsumptionProbability = AiAmmoConsumptionProbability;
+ return inst;
+ }
+ }
+}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.dll b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.dll
index 76d2690..9f59015 100644
--- a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.dll
+++ b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.dll
Binary files differ
diff --git a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.exe b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.exe
index bb1931a..c623fc8 100644
--- a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.exe
+++ b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.exe
Binary files differ
diff --git a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.pdb b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.pdb
index 109bb56..b10e380 100644
--- a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.pdb
+++ b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.pdb
Binary files differ
diff --git a/DungeonShooting_Godot/excel/excelFile/ActivityObject.xlsx b/DungeonShooting_Godot/excel/excelFile/ActivityObject.xlsx
index b5ef62e..e7f3499 100644
--- a/DungeonShooting_Godot/excel/excelFile/ActivityObject.xlsx
+++ b/DungeonShooting_Godot/excel/excelFile/ActivityObject.xlsx
Binary files differ
diff --git a/DungeonShooting_Godot/excel/excelFile/Weapon.xlsx b/DungeonShooting_Godot/excel/excelFile/Weapon.xlsx
index bd6cc04..70d7bb4 100644
--- a/DungeonShooting_Godot/excel/excelFile/Weapon.xlsx
+++ b/DungeonShooting_Godot/excel/excelFile/Weapon.xlsx
Binary files differ
diff --git a/DungeonShooting_Godot/src/config/ExcelConfig.cs b/DungeonShooting_Godot/src/config/ExcelConfig.cs
index 11458d0..c3e4ed0 100644
--- a/DungeonShooting_Godot/src/config/ExcelConfig.cs
+++ b/DungeonShooting_Godot/src/config/ExcelConfig.cs
@@ -37,6 +37,7 @@
_InitActivityObjectConfig();
_InitWeaponConfig();
+
}
private static void _InitActivityObjectConfig()
{
@@ -74,6 +75,7 @@
throw new Exception("初始化表'Weapon'失败!");
}
}
+
private static string _ReadConfigAsText(string path)
{
var file = FileAccess.Open(path, FileAccess.ModeFlags.Read);