使用方式:
写表
打开 Excel 目录下的 UnitConfig.xlsx
A1:根据该单元格内是否存在 AppType.ClientH 区别生成的是客户端还是服务器的配置
C3:从这里开始读取数据
读写规则:
第3行:该行为注释行内容不读取, # 开头该列不读取, s 开头该字段服务器专用
第4行:该行内容作为字段的名称,不可为空
第5行:该行内容作为字段的类型,不可为空
第6行及以下:配置的数据
嵌套
当你需要在列表里面嵌套的时候,我觉得你应该重新审视一下你的逻辑
如果你实在不想考虑了,一定要嵌套!那么你可以再开一个表,这个表就是嵌套的数据,然后在需要嵌套的表里面填写该表的数据的ID!
需要嵌套的表:
被嵌套的表:
大约这么去访问,就可以得到完整数据,对扩展也友好:
var testConfig = Game.Scene.GetComponent<ConfigComponent>().Get(typeof(TestConfig),1001) as TestConfig;
var test2 = Game.Scene.GetComponent<ConfigComponent>().Get(typeof(Test2Config), testConfig.a);
访问配置数据
// 读取 TestConfig 类型所有数据
var array = Game.Scene.GetComponent<ConfigComponent>().GetAll(typeof(TestConfig));
foreach (TestConfig config in array)
{
Log.Debug($"{config.a}");
}
注意事项:
id字段是不可缺少的,不能移除id字段
点击导出客户端配置或服务器配置时报一下错误,这是由于你正在使用独占模式打开Excel导致的,关闭正在修改的Excel就好
可读取字段中存在空白数据,字段数据是不允许空白的,必须写点什么
当然你觉得这很麻烦和自己的习惯不符,你也可以修改一下源码读到空白数据直接给与一个默认值之类的
但是并不赞成这么做。直接写在表上可以直接查询该值,更有利于阅读。
并且其他人阅读的时候不会疑惑这里为什么空白一片
删除了,又没有完全删除,按下delete删除了黄色列,但实际上读取的时候还是会读到,需要删除单元格才能正常读取
生成结果:
点击导出客户端配置或导出服务器配置即可
正常没有报错的情况下将会在 ET\Unity\Assets\Res\Config 文件夹生成对应的配置数据
并且在
Assets/Model/Module/Demo/Config
Assets/Hotfix/Module/Demo/Config
Server/Model/Module/Demo/Config
目录下生成配置类
模块源码:
编辑器扩展
目录:ET\Unity\Assets\Editor\ExcelExporterEditor\ExcelExporterEditor.cs
修改类生成目录,下面路径按照自己放置位置修改就行:
private void OnGUI()
{
try
{
const string clientPath = "./Assets/Res/Config";
if (GUILayout.Button("导出客户端配置"))
{
this.isClient = true;
ExportAll(clientPath);
ExportAllClass(@"./Assets/Model/Module/Demo/Config", "namespace ETModel\n{\n");
ExportAllClass(@"./Assets/Hotfix/Module/Demo/Config", "using ETModel;\n\nnamespace ETHotfix\n{\n");
Log.Info($"导出客户端配置完成!");
}
if (GUILayout.Button("导出服务端配置"))
{
this.isClient = false;
ExportAll(ServerConfigPath);
ExportAllClass(@"../Server/Model/Module/Demo/Config", "namespace ETModel\n{\n");
Log.Info($"导出服务端配置完成!");
}
}
catch (Exception e)
{
Log.Error(e);
}
}
扩展配置表支持的字段类型,需要支持更多类型在这里添加就可以了:
private static string Convert(string type, string value)
{
switch (type)
{
case "int[]":
case "int32[]":
case "long[]":
return $"[{value}]";
case "string[]":
return $"[{value}]";
case "int":
case "int32":
case "int64":
case "long":
case "float":
case "double":
return value;
case "string":
return $"\"{value}\"";
default:
throw new Exception($"不支持此类型: {type}");
}
}
配置加载
配置组件: ConfigComponent.cs
遍历所有配置类型,BeginInit初始化后添加到缓存
public void Load()
{
this.allConfig.Clear();
List<Type> types = Game.EventSystem.GetTypes();
foreach (Type type in types)
{
object[] attrs = type.GetCustomAttributes(typeof (ConfigAttribute), false);
if (attrs.Length == 0)
{
continue;
}
ConfigAttribute configAttribute = attrs[0] as ConfigAttribute;
// 只加载指定的配置
if (!configAttribute.Type.Is(AppType.ClientH))
{
continue;
}
object obj = Activator.CreateInstance(type);
ACategory iCategory = obj as ACategory;
if (iCategory == null)
{
throw new Exception($"class: {type.Name} not inherit from ACategory");
}
iCategory.BeginInit();
iCategory.EndInit();
this.allConfig[iCategory.ConfigType] = iCategory;
}
}
配置初始化
配置每一行作为一个类数据,反序列化json后保存到字典中
public override void BeginInit()
{
this.dict = new Dictionary<long, IConfig>();
string configStr = ConfigHelper.GetText(typeof (T).Name);
foreach (string str in configStr.Split(new[] { "\n" }, StringSplitOptions.None))
{
try
{
string str2 = str.Trim();
if (str2 == "")
{
continue;
}
T t = ConfigHelper.ToObject<T>(str2);
this.dict.Add(t.Id, t);
}
catch (Exception e)
{
throw new Exception($"parser json fail: {str}", e);
}
}
}