MyFramework:Unity 我的表格工具和 Luban 有什么区别
MyFramework 里有一套自己的表格工具链。
有人可能会问:
既然已经有 Luban 这种成熟的配置表工具,为什么 MyFramework 里还要保留自己的表格工具?
先说结论:
MyFramework 的表格工具不是为了替代 Luban。
Luban 是一个通用配置表解决方案,目标是服务不同项目、不同语言、不同引擎、不同数据格式。它官方介绍里也强调了数据校验、跨平台、主流引擎和热更新方案支持等能力。
MyFramework 的表格工具则不是通用工具。
它更像是项目内部的一套配置生产线。
它服务的是 MyFramework 自己的工程结构:
- Unity 客户端
- C++ 服务器
- CSV 配置表
- 自研表格编辑器
- 客户端代码生成
- 服务器代码生成
- 资源路径检查
- 表格引用检查
- 项目工程检查
- 运行时数据检查
项目地址:
https://github.com/ZHOURUIH/MyFramework
这篇文章不是要讨论谁更强,而是说清楚:
通用配置表工具和项目内表格工具链,到底有什么区别。
一、定位不同
Luban 的定位是通用配置表解决方案。
它要解决的是各种游戏项目都会遇到的配置问题:
- 表格怎么定义
- 数据怎么校验
- 代码怎么生成
- 多语言怎么支持
- 多引擎怎么接入
- 多种数据格式怎么导出
- 客户端和服务器怎么共用配置
所以 Luban 更像一个标准化配置基础设施。
它适合很多项目使用。
MyFramework 的表格工具定位更窄。
它不是为了适配所有项目,而是为了服务自己的项目结构。
我的项目里,配置表不是一个孤立工具,而是和框架里的其他系统绑定在一起:
- 资源管理
- 热更新代码结构
- 服务器框架
- 协议生成
- 工程检查
- 运行时配置加载
- AssetBundle 构建规则
所以 MyFramework 的表格工具更像框架内部工作流的一部分。
Luban 解决的是:
如何给各种项目提供一套通用配置表方案。
MyFramework 解决的是:
如何让自己的项目从表格编辑、检查、生成到运行时使用都形成闭环。
这是最核心的区别。
二、MyFramework 的表格不是只生成数据类
MyFramework 的表格代码里,生成结果不是只有一个数据类。
它大致会分成两层:
EDXXX:一行配置数据ExcelXXX:一张表的管理、查询、检查和扩展逻辑
比如怪物表的数据类是 EDMonster。
它是自动生成的:
// auto generate start
using System;
using System.Collections.Generic;
using UnityEngine;
// 怪物细分表
public class EDMonster : ExcelData
{
public static int WORLD_BOSS_ID = 370; // 世界boss-火焰巨神
public static EDMonster WORLD_BOSS; // 世界boss-火焰巨神
public string mName; // 怪物名字
public ushort mTemplateID; // 怪物模板ID,索引到MonsterTemplate表
public MONSTER_STRENGTH mStrengthType; // 怪物强度类型
public ushort mLevel; // 怪物等级
public int mHP; // 怪物血量
public ushort mMoveSpeed; // 怪物闲逛时的移动速度
public List<ushort> mSkill = new(); // 怪物技能列表
public List<ushort> mTelentBuff = new(); // 怪物天赋buff
public ushort mDisplayOrderID; // 在怪物图鉴中显示的顺序
public string mCustomNameColor; // 自定义的怪物名称颜色,如果设置了自定义颜色,将会覆盖怪物强度等级的颜色
public int mShowSound; // 出现在屏幕中时播放的音效
public float mShowSoundOdds; // 播放出现音效的几率
这里可以看到,生成代码不是简单把 CSV 原样读出来。
它已经转换成了项目里可以直接使用的强类型字段。
比如:
mTemplateIDmStrengthTypemSkillmTelentBuffmShowSound
这些字段和项目里的枚举、技能表、Buff 表、音效表都有关系。
这就是 MyFramework 的特点。
表格不是孤立的数据文件。
表格字段天然会和项目里的其他系统发生关系。
三、读取逻辑也是生成出来的
EDMonster 里不只是字段,还会生成读取逻辑。
例如:
public override bool read(SerializerRead reader)
{
bool result = base.read(reader);
result = result && reader.readString(out mName);
result = result && reader.read(out mTemplateID);
result = result && reader.readEnumByte(out mStrengthType);
result = result && reader.read(out mLevel);
result = result && reader.read(out mHP);
result = result && reader.read(out mMoveSpeed);
result = result && reader.readList(mSkill);
result = result && reader.readList(mTelentBuff);
result = result && reader.read(out mDisplayOrderID);
result = result && reader.readString(out mCustomNameColor);
result = result && reader.read(out mShowSound);
result = result && reader.read(out mShowSoundOdds);
return result;
}
这段代码说明一个事情:
MyFramework 的表格工具不是在运行时通过反射或动态字段名去读数据。
它会生成明确的读取代码。
字段是什么类型,就调用对应的读取接口。
比如:
- 字符串走
readString - 枚举走
readEnumByte - 列表走
readList - 普通数值走
read
这样做的好处是运行时更直接。
缺点是生成器和项目框架绑定更深。
这也是 MyFramework 和 Luban 的区别之一。
Luban 更强调通用配置生成能力。
MyFramework 更强调生成结果和自己运行时框架的配合。
四、表格注册也进入框架流程
MyFramework 里所有表都会进入统一注册流程。
比如 ExcelRegister 里会生成这样的注册代码:
public class ExcelRegister
{
public static void registeAll()
{
registeTable(out mExcelAchivement, typeof(EDAchivement), "Achivement");
registeTable(out mExcelAnimation, typeof(EDAnimation), "Animation");
registeTable(out mExcelBuff, typeof(EDBuff), "Buff");
registeTable(out mExcelBuffDetail, typeof(EDBuffDetail), "BuffDetail");
registeTable(out mExcelCondition, typeof(EDCondition), "Condition");
registeTable(out mExcelEffect, typeof(EDEffect), "Effect");
registeTable(out mExcelMonster, typeof(EDMonster), "Monster");
registeTable(out mExcelMonsterSkill, typeof(EDMonsterSkill), "MonsterSkill");
registeTable(out mExcelMonsterTemplate, typeof(EDMonsterTemplate), "MonsterTemplate");
registeTable(out mExcelSound, typeof(EDSound), "Sound");
// 进入热更以后,所有资源都处于可用状态
mExcelManager.resourceAvailable();
}
protected static void registeTable<T>(out T table, Type dataType, string tableName) where T : ExcelTable
{
table = mExcelManager.registe(tableName, typeof(T), dataType) as T;
}
}
这里能看到,MyFramework 的表格并不是各自独立加载。
所有表都会注册到 mExcelManager。
注册时会带上:
- 表名
- 表类型
- 数据类型
比如怪物表注册的是:
registeTable(out mExcelMonster, typeof(EDMonster), "Monster");
这意味着表格系统天然接入了框架的全局管理流程。
这和通用导表工具的关注点不一样。
Luban 更关心怎么生成不同项目都能使用的配置代码。
MyFramework 更关心这些表怎么进入自己的框架生命周期。
五、MyFramework 的表格类可以手写扩展
这一点很重要。
MyFramework 生成的数据类是 EDXXX。
但表管理类是 ExcelXXX,而且很多表类是 partial。
比如怪物表:
public partial class ExcelMonster : ExcelTableT<EDMonster>
{
protected List<EDMonster> mPreviewMonsterList;
public int getMonsterCount()
{
if (mPreviewMonsterList == null)
{
initMonsterList();
}
return mPreviewMonsterList.Count;
}
public List<EDMonster> getPreviewMonsterList()
{
if (mPreviewMonsterList == null)
{
initMonsterList();
}
return mPreviewMonsterList;
}
}
这部分就不是单纯的导表代码了。
它已经开始进入项目业务逻辑。
比如怪物图鉴需要一份可预览怪物列表,表格类里就可以增加:
- 缓存列表
- 排序逻辑
- 分页获取逻辑
- 过滤逻辑
怪物图鉴列表的初始化也直接写在表类里:
protected void initMonsterList()
{
if (mPreviewMonsterList != null)
{
return;
}
mPreviewMonsterList = new();
// 删除所有不需要出现在图鉴中的怪物
foreach (EDMonster item in queryAll())
{
mPreviewMonsterList.addIf(item, item.mDisplayOrderID > 0);
}
// 根据顺序排序
mPreviewMonsterList.Sort((a, b) => { return sign(a.mDisplayOrderID - b.mDisplayOrderID); });
}
这就是 MyFramework 的项目化特点。
表格类不只是“数据容器”。
它也可以承载和这张表强相关的查询、缓存、排序、检查逻辑。
这类设计不一定适合通用工具。
但在自己的项目里很方便。
因为很多表都有自己的业务查询方式。
如果全部放到外部系统里,反而会分散。
六、检查逻辑可以分成默认生成和手写补充
MyFramework 里表格检查不是一个统一的外部规则列表。
它会生成默认检查,也允许手写补充检查。
比如 ExcelMonster 里有手写检查:
public override void checkAllData()
{
base.checkAllData();
foreach (EDMonster item in queryAll())
{
mExcelMonsterTemplate.checkData(item.mTemplateID, item.mID, this);
mExcelMonsterSkill.checkData(item.mSkill, item.mID, this);
mExcelBuffDetail.checkData(item.mTelentBuff, item.mID, this);
}
}
它还会生成默认检查:
// auto generate start
protected override void checkAllDataDefault()
{
foreach (EDMonster item in queryAll())
{
mExcelMonsterTemplate.checkData(item.mTemplateID, item.mID, this);
checkEnum(item.mStrengthType, "mStrengthType", item.mID);
mExcelMonsterSkill.checkData(item.mSkill, item.mID, this);
mExcelBuffDetail.checkData(item.mTelentBuff, item.mID, this);
mExcelSound.checkData(item.mShowSound, item.mID, this);
}
}
protected override void postParseFile()
{
EDMonster.postLoadAll(this);
}
// auto generate end
这段代码很能体现 MyFramework 表格工具的特点。
它不是只生成字段。
它还会根据字段关系生成检查逻辑。
比如:
mTemplateID要检查MonsterTemplate表mStrengthType要检查枚举是否合法mSkill要检查MonsterSkill表mTelentBuff要检查BuffDetail表mShowSound要检查Sound表
这就是项目内表格工具的价值。
表格字段不是孤立字段。
字段背后有项目关系。
MyFramework 的生成器会把这些项目关系也生成到检查流程里。
七、Luban 的检查更通用,MyFramework 的检查更项目化
Luban 也有很强的数据校验能力。
比如官方文档里就有 ref 引用检查、path 资源路径检查、range 范围检查等校验器。
但 Luban 的检查更偏通用。
它需要适配各种项目。
MyFramework 的检查更偏项目化。
比如这段:
mExcelMonsterTemplate.checkData(item.mTemplateID, item.mID, this);
mExcelMonsterSkill.checkData(item.mSkill, item.mID, this);
mExcelBuffDetail.checkData(item.mTelentBuff, item.mID, this);
mExcelSound.checkData(item.mShowSound, item.mID, this);
这不是抽象的“引用检查”。
它直接就是项目里的表引用关系。
怪物表引用怪物模板表。
怪物表引用怪物技能表。
怪物表引用 BuffDetail 表。
怪物表引用 Sound 表。
这种检查和项目强绑定。
优点是检查很直接,问题定位也很直接。
缺点是通用性不高。
但 MyFramework 本来就不是要做一个通用导表器。
它要解决的是自己项目里的真实问题。
八、数据后处理也进入表格流程
EDMonster 里还有一个后处理函数:
public static void postLoadAll(ExcelTableT<EDMonster> table)
{
WORLD_BOSS = table.query(WORLD_BOSS_ID);
}
而 ExcelMonster 里生成的 postParseFile 会调用它:
protected override void postParseFile()
{
EDMonster.postLoadAll(this);
}
这说明 MyFramework 的表格加载流程不只是:
- 读取文件
- 生成对象
- 放进字典
它还会有表级别的后处理。
比如这里把世界 Boss 的配置缓存成静态对象:
public static EDMonster WORLD_BOSS;
这类需求在项目里很常见。
某些全局配置、特殊 ID、常用数据,需要在加载后直接缓存起来。
通用导表工具当然也可以做后处理。
但 MyFramework 的特点是,这个后处理流程已经是表格体系的一部分。
它和生成代码、表格注册、数据检查都在同一个工作流里。
九、MyFramework 更强调客户端和服务器配套
Luban 支持多语言、多平台,这是它的优势。
MyFramework 不追求支持那么多语言。
我的目标更明确:
- Unity 客户端生成 C# 表格代码
- C++ 服务器生成对应表格代码
- 客户端和服务器使用同一套配置定义
- 字段、ID、枚举、引用关系保持一致
这和 MyFramework 的定位有关。
MyFramework 不是一个单独客户端框架。
它还有配套服务器框架:
https://github.com/ZHOURUIH/MyServerFramework
所以表格工具必须考虑客户端和服务器协作。
Luban 是多语言通用生成。
MyFramework 是客户端和服务器项目配套生成。
这个目标更窄,但和我的项目更贴合。
十、为什么我没有直接换成 Luban
Luban 很成熟,也很强。
如果一个项目需要的是成熟通用导表方案,Luban 很合适。
尤其是这些情况:
- 需要多语言代码生成
- 需要复杂类型系统
- 需要多种数据源格式
- 需要多种导出格式
- 不想自己维护导表工具
- 希望配置工作流标准化
- 项目跨多个引擎或多个运行环境
但 MyFramework 的表格工具已经和项目流程绑得很深。
它不仅负责生成数据类,还负责:
- 注册表格
- 接入 ExcelManager
- 生成读取逻辑
- 生成默认检查逻辑
- 保留手写扩展逻辑
- 做表之间的引用检查
- 做枚举检查
- 做后处理
- 和客户端服务器流程配套
这些东西不是不能用 Luban 实现。
而是如果换成 Luban,我仍然需要在外面再包一层项目规则。
既然这套项目规则已经在 MyFramework 里跑通,那保留自己的表格工具链就有意义。
所以我的选择不是因为 Luban 不好。
而是因为 MyFramework 的表格工具已经是项目内部生产线的一部分。
十一、适合场景不同
Luban 更适合这些项目:
- 希望使用成熟通用配置方案
- 需要多语言代码生成
- 需要多种数据源格式
- 需要多种导出格式
- 需要复杂类型系统
- 不想自己维护导表工具
- 希望配置流程标准化
- 项目可能跨 Unity、Unreal、服务器、多语言环境
MyFramework 的表格工具更适合这些情况:
- 已经使用 MyFramework
- 客户端是 Unity
- 服务器使用配套 C++ 框架
- 表格格式希望统一
- 更重视项目内检查
- 希望和资源管理联动
- 希望和协议生成联动
- 希望和工程检查工具联动
- 希望表格类可以写项目扩展逻辑
- 希望工具链完全按自己的项目习惯定制
所以这两个工具不是替代关系。
Luban 更适合标准化通用配置流程。
MyFramework 的表格工具更适合自己的框架体系。
总结
MyFramework 的表格工具和 Luban 最大的区别,不在于某个功能点谁多谁少。
而在于定位不同。
Luban 是一个更通用、更完整的游戏配置解决方案。
它适合各种项目、各种语言、各种数据格式,也适合希望使用成熟导表工具的团队。
MyFramework 的表格工具则是一个更项目化、更框架内聚的配置工作流。
从代码上也能看出来:
EDMonster负责一行数据结构和读取ExcelMonster负责表级逻辑、查询缓存、数据检查和后处理ExcelRegister负责把所有表注册进mExcelManagercheckAllDataDefault负责生成默认表引用和枚举检查checkAllData可以继续补项目手写检查postParseFile可以做表加载后的后处理
所以 MyFramework 的表格工具不是单纯导表器。
它更像项目内部生产线的一部分。
我的理解是:
Luban 更像标准化配置基础设施。
MyFramework 的表格工具更像项目内部生产线。
标准化工具适合解决通用问题。
项目内部生产线适合解决自己项目里的具体问题。
这就是我在 MyFramework 里保留自研表格工具链的原因。
更多推荐
所有评论(0)