Unity游戏配置管理新思路:Luban插件实现Excel到Json自动化流程
1. 项目概述:为什么我们需要新的配置管理思路?
在Unity游戏开发中,配置管理是个老生常谈但又极其核心的话题。从早期的ScriptableObject,到直接读取CSV、XML,再到如今主流的Json,每个团队似乎都有一套自己的“祖传”配置表处理流程。我经历过一个中型MMO项目,策划同学每天要更新几十张Excel表,程序同学则需要手动执行“导出-转换-导入-重启编辑器”这一套繁琐操作,不仅效率低下,还极易在多人协作时出现版本错乱,一个手滑覆盖了别人的配置,半天时间就搭进去了。这种痛点催生了我们对自动化、规范化配置流程的迫切需求。
“Unity游戏配置管理新思路:用Luban插件实现Excel到Json的自动化流程”这个标题,精准地指向了解决这一系列痛点的核心方案。它不是一个简单的工具介绍,而是一套从数据生产、校验、转换到最终在Unity中加载使用的完整工程化解决方案。Luban本身是一个强大的配置代码及数据生成工具,而将其与Unity工作流深度集成,正是我们这次要深入探讨的“新思路”。
这套思路的价值在于,它将策划(Excel)、程序(代码)、数据(Json)三者通过一条自动化流水线串联起来。策划可以在熟悉的Excel环境中维护复杂的配置关系,Luban负责进行强类型校验、生成对应的C#数据结构和高效的二进制或Json数据文件,Unity则在运行时通过生成的加载代码无缝使用这些配置。整个过程无需人工干预,一键完成,极大地提升了开发效率和数据可靠性。接下来,我将结合实战,为你拆解如何搭建这套流程,并深入单表加载与保存的每一个细节。
2. 核心思路与工具选型:为什么是Luban?
在决定采用Luban之前,我们团队也评估过不少方案。比如,直接使用Unity的JsonUtility或Newtonsoft.Json反序列化由Excel手动导出的Json文件。这种方式看似简单,但问题很多:首先,数据校验完全依赖策划自觉,类型错误、格式错误、引用缺失等问题在运行时才会暴露,调试成本高;其次,Excel中复杂的多表关联、继承、多态结构,在手动导出时很难保持其关系,最终在代码里还是需要大量手工代码去组织数据;再者,没有强类型的代码提示,读取配置时写字符串Key极易出错。
我们也考虑过一些Unity Asset Store上的Excel插件,它们通常能很好地解决读取问题,但往往在数据转换、代码生成和持续集成(CI)支持上比较薄弱。而Luban的设计哲学恰好弥补了这些短板。
2.1 Luban的核心优势解析
Luban不是一个简单的文件转换器,它是一个“配置编译”系统。你可以把它理解为一个针对游戏配置数据的专用编译器。它的工作流程高度模仿了编程语言:源代码(Excel) -> 编译(Luban生成) -> 目标代码(C#/Java等代码和Json/Bin等数据)。
第一,强类型与代码生成。这是Luban的基石。你需要在定义文件(通常是.xml或.yaml)中声明每个配置表(如Item.xlsx)对应的数据结构。Luban会根据这个定义,生成完全对应的、强类型的C#类(如ItemConfig)。这意味着在Unity中,你访问配置字段时拥有完整的代码补全和类型检查,将运行时错误提前到了编译期。
第二,强大的数据校验与约束。在定义文件中,你可以为每个字段添加丰富的约束条件,比如数值范围(min:1 max:100)、正则表达式匹配、非空检查、引用其他表是否存在(外键约束)。Luban在转换过程中会严格执行这些校验,任何不合格的数据都会导致生成失败并给出明确错误信息,从源头保证了数据质量。
第三,支持复杂的数据关系。游戏配置远不止简单的列表。Luban原生支持多表关联、继承、多态、分组、嵌套结构等。例如,一个任务配置表可以继承自一个基础任务模板;一个道具配置可以包含一个“效果”结构体数组,而每个效果又可能引用技能表里的某个技能ID。这些复杂关系都能在Excel中直观体现,并由Luban在生成代码和数据时完美保持。
第四,多输出格式与高性能。Luban可以同时生成Json(人类可读,便于调试)、二进制(体积小,加载快)、Lua表等多种格式的数据文件,以及对应语言的加载代码。你可以根据项目阶段(开发期用Json,发布期用二进制)灵活选择。
第五,无缝的CI/CD集成。整个生成过程可以通过命令行调用,这使其可以轻松集成到Jenkins、GitLab CI等自动化流水线中。策划提交Excel到版本库后,CI自动触发Luban生成,并打包数据到资源服务器,实现了配置管理的全自动化。
基于以上几点,Luban为我们提供了一条从数据生产到消费的“高速公路”,而不仅仅是“一条乡间小路”。选择它,是选择了一整套工程化的解决方案。
2.2 环境准备与项目结构规划
在开始动手前,合理的项目结构是成功的一半。一个清晰的目录划分能让后续的维护和团队协作事半功倍。
我建议的Unity项目目录结构如下(仅展示相关部分):
Assets/ ├── Luban/ │ ├── Gen/ # 存放Luban生成的C#代码(不应手动修改) │ │ ├── Config/ │ │ │ ├── ItemConfig.cs │ │ │ └── ... │ │ └── Tables.cs # 统一的配置加载入口类 │ └── Lib/ # 存放Luban的运行时DLL(如 Luban.Runtime.dll) ├── Resources/Config/ # 存放生成的Json数据文件(如果使用Resources加载) ├── Editor/ # 存放编辑器扩展脚本 │ └── LubanGenerator.cs # 一键生成配置的编辑器脚本 └── Scripts/ # 项目业务逻辑代码在项目根目录(与Assets同级),我们建立配置的“源文件”目录,它独立于Unity工程,便于版本管理和CI操作:
ProjectRoot/ ├── Assets/ # Unity工程目录 ├── Config/ # 配置源文件目录 │ ├── Datas/ # 所有Excel配置表 │ │ ├── Item.xlsx │ │ ├── Skill.xlsx │ │ └── ... │ ├── Defines/ # Luban定义文件(.xml 或 .yaml) │ │ └── __tables__.xml │ └── Generate.bat/.sh # 本地生成脚本 └── ...工具安装:
- 安装 .NET SDK:Luban是一个.NET工具,需要安装.NET 6.0或更高版本的SDK。去微软官网下载安装即可。
- 获取Luban:从Luban的GitHub仓库发布页下载最新的发布包(如
luban-release.zip),解压到任意本地目录,例如D:\Tools\Luban。将其tools子目录路径添加到系统环境变量PATH中,方便命令行调用。 - Unity准备:在Unity项目中,你需要引用Luban的运行时库。通常将下载包中的
Luban.Runtime.dll(或对应版本的Unity包)放入项目的Assets/Luban/Lib目录下。
这样的结构分离了“数据源”、“生成代码”和“运行时数据”,职责清晰,是实践Luban工作流的最佳起点。
3. 从Excel到Json:自动化流程搭建实战
有了理论基础和准备,我们开始搭建核心的自动化流程。这个过程的目标是:策划在Config/Datas/下修改Excel -> 执行一个命令或点击一个按钮 -> Unity工程内自动更新生成的C#代码和Json数据文件。
3.1 定义数据表结构(Schema)
一切始于定义。我们需要告诉Luban,我们的Excel表长什么样,每列代表什么数据类型。这通过定义文件(schema)完成,通常使用XML格式,命名为__tables__.xml,放在Config/Defines/目录下。
假设我们有一个道具表Item.xlsx,内容如下:
| id | name | type | quality | useEffect |
|---|---|---|---|---|
| 1001 | 小型生命药水 | Consumable | 1 | heal:50 |
| 1002 | 力量之剑 | Weapon | 3 | attack:15 |
| 2001 | 传送卷轴 | Special | 2 | teleport |
对应的定义文件可以这样写:
<?xml version="1.0" encoding="utf-8" ?> <schema> <!-- 定义一个枚举,用于道具类型 --> <enum name="ItemType" value_type="int"> <var name="Consumable" value="1"/> <var name="Weapon" value="2"/> <var name="Armor" value="3"/> <var name="Special" value="4"/> </enum> <!-- 定义一个枚举,用于道具品质 --> <enum name="QualityType" value_type="int"> <var name="Normal" value="1"/> <var name="Rare" value="2"/> <var name="Epic" value="3"/> </enum> <!-- 定义道具表 --> <table name="TbItem" input="Datas/Item.xlsx" output="Datas/Item.json" mode="one"> <!-- 索引字段,必须是唯一且非空的整数或字符串 --> <var name="id" type="int" index="true"/> <!-- 名字,字符串类型 --> <var name="name" type="string"/> <!-- 类型,引用上面定义的ItemType枚举 --> <var name="type" type="ItemType"/> <!-- 品质,引用QualityType枚举 --> <var name="quality" type="QualityType"/> <!-- 使用效果,是一个字符串,可以为空 --> <var name="useEffect" type="string" nullable="true"/> </table> </schema>关键点解析:
<enum>:定义枚举类型。将Excel中的数字或字符串映射为有意义的枚举值,在生成的C#代码中会变成强类型枚举,极大提升代码可读性和安全性。<table>:定义一张配置表。name: 生成的加载类名,通常以Tb(Table的缩写)开头,如TbItem。input: Excel源文件路径,相对于定义文件或执行目录。output: 生成的数据文件路径和名称。这里我们指定生成Json。mode: 表模式。one表示每行数据对应一个独立配置项,是最常用的模式。还有list(整个表是一个列表)、map(键值对)等。
<var>:定义表中的列。name: 必须与Excel表第一行(标题行)的列名完全一致。type: 数据类型,如int,string,bool,float,也可以是自定义的enum或其他table类型(用于关联)。index="true": 指定该列为索引列。Luban会以此列为Key生成高效的字典数据结构,用于快速查找。nullable="true": 允许该字段为空(Excel中留空)。
注意:Excel表的第一行必须是列名(字段名),第二行开始才是数据。Luban默认第一张工作表(Sheet)为数据表。复杂的多级结构(如数组、嵌套)可以通过在列名中使用
::分隔符或定义bean来实现,这里先以基础单表为例。
3.2 编写生成脚本与集成Unity Editor
定义写好,Excel数据填好,接下来就是执行生成。我们可以在项目根目录创建一个批处理脚本Generate.bat(Windows)或Shell脚本Generate.sh(Mac/Linux)。
Generate.bat 内容示例:
@echo off set LUBAN_PATH=D:\Tools\Luban\tools\luban.exe set CONF_ROOT=%~dp0Config set UNITY_ASSETS_PATH=%~dp0Assets echo 正在清理旧生成文件... if exist "%UNITY_ASSETS_PATH%\Luban\Gen" rmdir /s /q "%UNITY_ASSETS_PATH%\Luban\Gen" if exist "%UNITY_ASSETS_PATH%\Resources\Config" rmdir /s /q "%UNITY_ASSETS_PATH%\Resources\Config" echo 正在使用Luban生成配置... %LUBAN_PATH% ^ --define_file %CONF_ROOT%\Defines\__tables__.xml ^ --input_data_dir %CONF_ROOT%\Datas ^ --output_code_dir %UNITY_ASSETS_PATH%\Luban\Gen ^ --output_data_dir %UNITY_ASSETS_PATH%\Resources\Config ^ --gen_types "code_cs_unity_json,data_json" ^ --service all if %errorlevel% equ 0 ( echo 生成成功! pause ) else ( echo 生成失败,请检查错误信息。 pause exit /b 1 )关键参数解释:
--define_file: 指定定义文件路径。--input_data_dir: 指定Excel数据目录。--output_code_dir: 指定生成的C#代码输出目录(放到Unity的Assets下)。--output_data_dir: 指定生成的Json数据文件输出目录(放到Unity的Resources下,便于加载)。--gen_types: 指定生成类型。code_cs_unity_json表示生成适用于Unity的、支持Json加载的C#代码;data_json表示生成Json格式数据。--service all: 生成所有定义的表。
双击运行这个批处理,如果一切顺利,你会在Assets/Luban/Gen/下看到生成的ItemConfig.cs等C#文件,在Assets/Resources/Config/下看到Item.json等数据文件。
更进一步:Unity编辑器一键生成让策划或非技术同学去运行命令行脚本不太友好。我们可以在Unity中创建一个编辑器脚本,来封装这个调用过程。
在Assets/Editor/下创建LubanGenerator.cs:
using UnityEditor; using UnityEngine; using System.Diagnostics; using System.IO; public static class LubanGenerator { [MenuItem("Tools/Luban/Generate Configs")] public static void Generate() { string projectRoot = Path.GetFullPath(Path.Combine(Application.dataPath, "..")); string lubanExePath = @"D:\Tools\Luban\tools\luban.exe"; // 根据你的实际路径修改 string defineFile = Path.Combine(projectRoot, @"Config\Defines\__tables__.xml"); string inputDataDir = Path.Combine(projectRoot, @"Config\Datas"); string outputCodeDir = Path.Combine(Application.dataPath, @"Luban\Gen"); string outputDataDir = Path.Combine(Application.dataPath, @"Resources\Config"); // 清理旧目录 if (Directory.Exists(outputCodeDir)) Directory.Delete(outputCodeDir, true); if (Directory.Exists(outputDataDir)) Directory.Delete(outputDataDir, true); Directory.CreateDirectory(outputCodeDir); Directory.CreateDirectory(outputDataDir); // 构建命令行参数 string args = string.Format( "--define_file {0} --input_data_dir {1} --output_code_dir {2} --output_data_dir {3} --gen_types \"code_cs_unity_json,data_json\" --service all", defineFile, inputDataDir, outputCodeDir, outputDataDir ); ProcessStartInfo startInfo = new ProcessStartInfo { FileName = lubanExePath, Arguments = args, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true }; using (Process process = Process.Start(startInfo)) { string output = process.StandardOutput.ReadToEnd(); string error = process.StandardError.ReadToEnd(); process.WaitForExit(); if (process.ExitCode == 0) { UnityEngine.Debug.Log("Luban 配置生成成功!\n" + output); AssetDatabase.Refresh(); // 刷新Unity资源数据库 } else { UnityEngine.Debug.LogError("Luban 配置生成失败!\n" + error); } } } }这样,在Unity编辑器的菜单栏Tools/Luban/下就会出现一个Generate Configs的按钮,点击即可一键完成所有配置的生成和刷新,对策划和测试同学极其友好。
4. 单表加载与保存实战:在Unity中使用配置
生成工作完成后,重头戏来了:如何在游戏运行时使用这些配置?Luban为我们生成了两个核心部分:数据类(如ItemConfig)和表加载类(如TbItem)。
4.1 生成的代码结构解析
打开Assets/Luban/Gen/Config/ItemConfig.cs,你会看到类似以下结构的代码(已简化):
namespace cfg { public partial class ItemConfig { public readonly int Id; public readonly string Name; public readonly ItemType Type; public readonly QualityType Quality; public readonly string UseEffect; public ItemConfig(JSONNode _json) { Id = _json["id"]; Name = _json["name"]; Type = (ItemType)_json["type"].AsInt; Quality = (QualityType)_json["quality"].AsInt; UseEffect = _json["useEffect"] != null ? _json["useEffect"] : null; } } }同时,在Assets/Luban/Gen/Tables.cs中,会有所有表的加载入口:
namespace cfg { public class Tables { public cfg.TbItem TbItem { get; private set; } public Tables(System.Func<string, JSONNode> loader) { TbItem = new cfg.TbItem(loader("Config/Item")); } } }而TbItem类则封装了所有ItemConfig的实例,并提供了通过ID快速查找的方法:
namespace cfg { public class TbItem { private readonly Dictionary<int, ItemConfig> _dataMap; public ItemConfig Get(int id) => _dataMap.TryGetValue(id, out var v) ? v : null; public Dictionary<int, ItemConfig> DataMap => _dataMap; // ... 可能还有其他方法,如 GetAll() } }4.2 初始化与加载配置
在Unity游戏启动时(例如在某个Manager的Awake或Start方法中),我们需要初始化这个Tables类。Luban生成的code_cs_unity_json类型代码,默认依赖一个从Resources加载Json文本并解析为JSONNode的加载器。
一个标准的初始化流程如下:
using cfg; // 引入Luban生成的命名空间 using UnityEngine; public class ConfigManager : MonoBehaviour { private Tables _tables; public static ConfigManager Instance { get; private set; } private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); return; } Instance = this; DontDestroyOnLoad(gameObject); LoadAllConfigs(); } private void LoadAllConfigs() { // 定义加载器:根据传入的filepath(不含后缀),从Resources加载Json文本 System.Func<string, SimpleJSON.JSONNode> loader = (filepath) => { // 注意:生成时指定的output_data_dir是`Resources/Config`,所以文件路径是`Config/Item` // Resources.Load<TextAsset>需要传入在Resources文件夹下的相对路径,且不带后缀 TextAsset textAsset = Resources.Load<TextAsset>(filepath); if (textAsset == null) { Debug.LogError($"配置文件加载失败: {filepath}"); return null; } return SimpleJSON.JSON.Parse(textAsset.text); }; _tables = new Tables(loader); Debug.Log("所有配置表加载完成。"); } // 提供对外的访问接口 public Tables GetTables() => _tables; }4.3 在游戏逻辑中使用配置
加载完成后,在游戏的任何地方,你都可以通过ConfigManager.Instance.GetTables().TbItem来访问道具表。
示例:根据道具ID创建道具实例
public class ItemSystem { public void UseItem(int itemId) { // 1. 获取配置 ItemConfig itemCfg = ConfigManager.Instance.GetTables().TbItem.Get(itemId); if (itemCfg == null) { Debug.LogError($"找不到道具配置,ID: {itemId}"); return; } // 2. 使用强类型字段,有代码提示! Debug.Log($"使用道具: {itemCfg.Name} [类型:{itemCfg.Type}, 品质:{itemCfg.Quality}]"); // 3. 根据配置执行逻辑 switch (itemCfg.Type) { case ItemType.Consumable: if (!string.IsNullOrEmpty(itemCfg.UseEffect)) { // 解析效果字符串,例如"heal:50" ApplyEffect(itemCfg.UseEffect); } break; case ItemType.Weapon: // 装备武器逻辑 EquipWeapon(itemId); break; // ... 其他类型处理 } } private void ApplyEffect(string effectStr) { // 解析效果字符串的实现 // 例如:split by ':' etc. } }使用体验的提升是巨大的:
- 强类型安全:
itemCfg.Type是ItemType枚举,不是int或string,写switch语句时,所有分支都有提示,不可能拼错。 - 无魔法字符串:不需要写
itemCfg["name"]这样的字符串Key,彻底避免了因拼写错误导致的运行时空引用。 - 高性能:
Get(itemId)是通过字典查找,时间复杂度是O(1),效率远高于遍历列表。
4.4 配置的热重载与保存(编辑器扩展)
在开发阶段,我们经常需要修改配置后快速在游戏中看到效果,而不想重启游戏。这就需要“热重载”功能。同时,有时游戏运行时的数据(如玩家自定义的配置)也需要保存回Json格式。
热重载实现思路:在编辑器模式下,我们可以监听配置文件的改动(使用FileSystemWatcher或Unity的AssetPostprocessor),当检测到Resources/Config/下的Json文件发生变化时,重新调用Tables的构造函数来加载配置。由于配置类都是readonly的,重新加载后,所有引用到旧配置的地方需要更新。一种简单做法是发布一个“配置重载完成”的事件,让相关系统重新从ConfigManager获取最新的配置引用。
将数据保存回Json:Luban生成的是只读的运行时代码,主要用于加载。如果你需要将游戏内的数据(比如玩家编辑的阵容)保存为与配置相同结构的Json,你需要手动实现序列化。可以利用生成的类作为模板,创建对应的可序列化类([System.Serializable]),或者直接使用SimpleJSON或Newtonsoft.Json库来构建相同的JSON结构进行保存。
例如,使用SimpleJSON保存一个ItemConfig结构的数据:
using SimpleJSON; public JSONNode SaveItemData(MyRuntimeItem runtimeItem) { JSONObject json = new JSONObject(); json["id"] = runtimeItem.Id; json["name"] = runtimeItem.Name; json["type"] = (int)runtimeItem.Type; // 枚举转int json["quality"] = (int)runtimeItem.Quality; if (!string.IsNullOrEmpty(runtimeItem.UseEffect)) json["useEffect"] = runtimeItem.UseEffect; // 将JSONNode转换为字符串保存 string jsonStr = json.ToString(); // System.IO.File.WriteAllText(...) return json; }实操心得:热重载功能在开发UI、调整数值时非常有用,可以做到“改表即生效”。但要注意处理好对象引用更新,避免出现空引用或状态不一致。对于保存功能,建议将“运行时动态数据”和“静态配置数据”的序列化/反序列化方案区分开,配置数据用Luban生成的只读加载器,动态数据则用更灵活的Json库。
5. 常见问题、排查技巧与进阶优化
在实际项目接入Luban的过程中,你肯定会遇到各种各样的问题。下面是我踩过的一些坑和总结的排查技巧。
5.1 生成失败常见错误与解决
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| Luban执行报错:未找到输入文件 | 1. Excel文件路径在定义文件中写错。 2. Excel文件被其他程序(如Excel编辑器)打开占用。 | 1. 检查__tables__.xml中<table>的input属性路径,确保相对于定义文件或执行目录是正确的。2. 关闭Excel文件。 |
| Luban执行报错:字段类型不匹配 | 1. Excel中某单元格的数据类型与定义文件中type不匹配(如在int列填了字符串)。2. 枚举值在Excel中填写了未定义的数字或文本。 | 1. 仔细阅读Luban的错误输出,它会精确到文件、行、列。修正Excel中的数据。 2. 确保Excel中填写的枚举值是定义文件中存在的 value或name。 |
Unity编译错误:找不到cfg命名空间 | 1. 生成的C#代码没有放在Unity的Assets目录下,或不在Editor/Scripts等编译路径中。2. 生成代码后未刷新Unity项目。 | 1. 确保--output_code_dir指向了Assets下的某个目录(如Assets/Luban/Gen)。2. 生成后,在Unity编辑器中选择 Assets -> Refresh,或调用AssetDatabase.Refresh()。 |
| 运行时错误:Json解析失败/空引用 | 1. 生成的Json数据文件没有放到正确的加载路径下(如Resources)。2. Resources.Load的路径参数错误,或文件扩展名.json被包含进去了。3. Json文件格式损坏(可能在生成过程中被中断)。 | 1. 检查--output_data_dir路径,并确认文件已生成。2. Resources.Load<TextAsset>("Config/Item"),路径是相对于Resources文件夹的,且不包含后缀名。3. 重新执行生成命令。 |
生成的C#类字段全是null或默认值 | 1. Excel表头(第一行)的列名与定义文件<var>中的name不匹配(大小写、空格、中英文符号)。2. Excel有多个工作表,数据不在第一个Sheet。 | 1. 严格保证两者一致。建议直接复制Excel表头到定义文件中。 2. Luban默认读取第一个工作表。如需指定,可在 input属性后加#SheetName,如input="Datas/Item.xlsx#道具表"。 |
5.2 性能优化与内存管理
当配置表数量巨大(几千上万行)时,加载和内存需要关注。
使用二进制格式替代Json:在发布版本中,将生成类型从
data_json改为data_bin。二进制格式文件更小,加载更快,且解析(反序列化)速度远超Json。只需在生成命令中修改--gen_types为code_cs_unity_bin,data_bin,并实现一个从二进制流加载的loader即可。Luban.Runtime已提供了相应的ByteBuf加载器。分模块按需加载:不要一次性加载所有配置。可以将配置表按模块划分(如
基础表、战斗表、剧情表),为每个模块创建独立的定义文件和生成命令。游戏运行时,只加载当前所需模块的配置。注意字符串驻留:配置表中大量的重复字符串(如相同的描述文本)会占用额外内存。Luban本身不会做字符串驻留。如果内存敏感,可以考虑在定义文件中将常用字符串定义为
string类型的共享引用(Luban支持),或者在加载后由游戏逻辑自行管理一个字符串缓存池。
5.3 应对复杂数据结构
前面演示的是平坦的单表。实际项目中会遇到复杂结构。
- 多列集合(数组):在Excel中,可以用
|分隔的字符串表示数组,如skills:1001|1002|1003,在定义中类型写int[]。或者使用item1,item2,item3的列命名方式(如drop_items1,drop_items2),Luban会自动识别为数组。 - 嵌套结构(Bean):在定义文件中使用
<bean>定义一个结构体,然后在表的<var>中type引用这个bean。在Excel中,可以用子列表示,如reward::id,reward::count。 - 多表关联与引用:这是Luban的强项。例如,道具表有一个字段
equip_skill_id,它引用技能表Skill的id。只需在定义中写type="cfg.SkillConfig"(假设技能表生成的类名是SkillConfig)。Luban会在生成时进行引用完整性检查,并在代码中直接为你生成一个SkillConfig类型的字段,通过它可以直接访问关联的技能配置,无需手动查找。
5.4 与版本控制系统(如Git)的协作
配置表是项目重要的资产,需要纳入版本管理。
- 忽略生成文件:在
.gitignore中,忽略Assets/Luban/Gen/和Assets/Resources/Config/(或你的输出目录)。只提交Config/Datas/和Config/Defines/下的源文件(Excel和定义文件)。生成文件应由CI或每个开发者的本地生成脚本产生。 - 解决合并冲突:Excel文件是二进制格式,Git无法合并。当多人同时修改一张Excel表时,极易冲突。最佳实践是:建立规则,一个时间段内一张表只由一个人修改。如果冲突不可避免,可以考虑将Excel拆分为更小的表,或者使用支持更好合并的格式(如CSV),但CSV在表示复杂结构时不如Excel直观。
- CI/CD集成:在Git服务器(如GitLab)上配置CI流水线。当有提交到
Config/Datas/或Config/Defines/目录时,自动触发Luban生成任务,并将生成的数据文件打包到资源服务器或直接提交到资源仓库的一个特定分支。这确保了线上环境配置的准确性和及时性。
接入Luban初期会有一个学习和适配的成本,尤其是定义文件的编写和复杂数据结构的梳理。但一旦流程跑通,它带来的开发效率提升、数据质量保障和团队协作的顺畅感,会让你觉得所有投入都是值得的。它不仅仅是一个工具,更是一种规范,引导团队以更工程化的方式对待游戏配置数据。
