游戏配置表导出工具深度解析

文章摘要

TableExportTool 是一个用于表格数据导出的工具,主要包含表格读取、数据解析、导出和代码生成四大模块。它支持读取 Excel/CSV 文件,解析字段和类型后转换为 JSON、二进制、Lua 等多种格式,并自动生成 C#、Lua 等数据结构代码。工具还提供 Unity 集成功能,支持一键导出、Asset生成和热更新。核心流程包括读取表头、类型校验、数据组装和导出,通过 NPOI/EPPlus 实现表格解析,并支持自定义类型转换和外键校验。典型应用场景是游戏配置表管理,可扩展多语言和嵌套结构等高级功能。


1. 整体架构

TableExportTool 主要由以下几个模块组成:

  • 表格读取模块:读取 Excel/CSV 文件,解析 Sheet。
  • 数据解析模块:解析字段名、类型、数据行,做类型转换和校验。
  • 数据导出模块:导出为 JSON、二进制、Lua、C#等格式。
  • 代码生成模块:根据表结构自动生成 C#、Lua、TS 等数据结构代码。
  • Unity集成模块:在 Unity Editor 中一键导出、生成 Asset、支持热更。

2. 核心流程

  1. 扫描表格目录,找到所有 Excel/CSV 文件。
  2. 遍历每个表格文件,对每个 Sheet 进行处理。
  3. 读取表头(字段名、类型),解析数据行。
  4. 类型转换与校验,如 int、float、string、bool、array、enum、外键等。
  5. 组装数据结构,如 List/Dictionary。
  6. 导出数据(JSON、二进制、Lua等)。
  7. 自动生成代码(C#类、Lua表、TS接口等)。
  8. Unity集成,如生成 ScriptableObject、AssetBundle、热更支持。

3. 关键代码逻辑(以 C# 为例)

3.1 读取 Excel 表格

使用 NPOI 或 EPPlus 读取 Excel 文件。

using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;

public IWorkbook LoadWorkbook(string path)
{
    using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
    {
        return new XSSFWorkbook(fs);
    }
}

3.2 解析表头和类型

ISheet sheet = workbook.GetSheetAt(0);
IRow fieldRow = sheet.GetRow(0); // 字段名
IRow typeRow = sheet.GetRow(1);  // 类型
List<string> fieldNames = new List<string>();
List<string> fieldTypes = new List<string>();
for (int i = 0; i < fieldRow.LastCellNum; i++)
{
    fieldNames.Add(fieldRow.GetCell(i).StringCellValue.Trim());
    fieldTypes.Add(typeRow.GetCell(i).StringCellValue.Trim());
}

3.3 读取数据行并类型转换

List<Dictionary<string, object>> dataList = new List<Dictionary<string, object>>();
for (int i = 2; i <= sheet.LastRowNum; i++)
{
    IRow row = sheet.GetRow(i);
    if (row == null) continue;
    // 跳过注释/空行
    if (row.GetCell(0) == null || row.GetCell(0).ToString().StartsWith("#")) continue;

    Dictionary<string, object> item = new Dictionary<string, object>();
    for (int j = 0; j < fieldNames.Count; j++)
    {
        string type = fieldTypes[j];
        var cell = row.GetCell(j);
        object value = ConvertCell(cell, type);
        item[fieldNames[j]] = value;
    }
    dataList.Add(item);
}

3.4 类型转换函数

object ConvertCell(ICell cell, string type)
{
    if (cell == null) return GetDefault(type);
    string str = cell.ToString();
    switch (type)
    {
        case "int": return int.TryParse(str, out var i) ? i : 0;
        case "float": return float.TryParse(str, out var f) ? f : 0f;
        case "bool": return str == "1" || str.ToLower() == "true";
        case "string": return str;
        case "array_int": return str.Split('|').Select(s => int.Parse(s)).ToArray();
        // 可扩展 array_float, array_string, enum, struct 等
        default: return str;
    }
}

3.5 导出为 JSON

string json = JsonConvert.SerializeObject(dataList, Formatting.Indented);
File.WriteAllText($"{outDir}/{sheetName}.json", json, Encoding.UTF8);

3.6 导出为二进制

可用 protobuf、MessagePack、自己写二进制序列化等。


4. 代码自动生成

4.1 生成 C# 类

根据字段名和类型自动生成 C# 数据结构:

public class {TableName}
{
    public int id;
    public string name;
    public int hp;
    public int[] skills;
}

实现方式:用模板字符串,遍历字段名和类型,拼接生成代码文件。

4.2 生成 Lua/TS 结构

同理,生成 Lua table、TS interface 等。


5. Unity 集成

  • Editor 菜单:通过 [MenuItem("Tools/TableExportTool/Export All")] 挂载一键导出入口。
  • 自动 Asset 生成:导出 ScriptableObject、AssetBundle,或 Resources 目录下的 JSON/二进制。
  • 热更支持:可在运行时重新加载配置表。

6. 进阶扩展

  • 外键校验:如 weapon.bullet_id 必须在 bullet 表中存在。
  • 唯一性校验:如 id 字段唯一。
  • 多语言支持:如导出多语言文本表。
  • 自定义类型/嵌套结构:如 struct、array_struct。
  • 表格注释/分表导出:支持注释行、分 Sheet 导出。

7. 典型目录结构

/TableExportTool/
    /Editor/
        TableExportTool.cs
        ExcelReader.cs
        CodeGenerator.cs
    /ConfigTables/
        Hero.xlsx
        Weapon.xlsx
    /Exported/
        Hero.json
        Weapon.json
        Hero.cs
        Weapon.cs

8. 参考开源项目

  • tenvick/TableExportTool
  • zwcloud/Configer
  • Unity-Excel-Exporter

9. 总结

TableExportTool 的详细实现核心是:

  • 读取表格解析字段/类型/数据类型转换与校验导出多格式数据自动生成代码Unity 集成与热更

下面我将针对你关心的类型扩展、代码生成模板、Unity集成三部分,分别给出详细的实现思路和关键代码示例。以 C#(Unity 环境)为例,便于你直接集成到实际项目中。


一、类型扩展(如支持 array_float、enum、自定义 struct)

1.1 支持 array_float

在类型解析和转换时,增加对 array_float 的支持:

object ConvertCell(ICell cell, string type)
{
    if (cell == null) return GetDefault(type);
    string str = cell.ToString();
    switch (type)
    {
        case "int": return int.TryParse(str, out var i) ? i : 0;
        case "float": return float.TryParse(str, out var f) ? f : 0f;
        case "bool": return str == "1" || str.ToLower() == "true";
        case "string": return str;
        case "array_int": return str.Split('|').Where(s => !string.IsNullOrEmpty(s)).Select(s => int.Parse(s)).ToArray();
        case "array_float": return str.Split('|').Where(s => !string.IsNullOrEmpty(s)).Select(s => float.Parse(s)).ToArray();
        // 下面是enum和struct的例子
        case "enum": return str; // 你可以在代码中定义enum类型并转换
        case "struct": return ParseStruct(str); // 见下
        default: return str;
    }
}

1.2 支持 enum

假设你有一列类型为 enum,如 Color,Excel中填 RedBlue 等。你可以在代码生成时自动生成 C# enum,并在数据加载时用 Enum.Parse 转换。

// 代码生成时
public enum Color
{
    Red,
    Blue,
    Green
}

// 数据加载时
case "enum": return Enum.Parse(typeof(Color), str);

1.3 支持 struct

假设 Excel 某列类型为 struct,内容如 1,2,3,你定义一个结构体:

public struct Vector3
{
    public float x, y, z;
    public Vector3(float x, float y, float z) { this.x = x; this.y = y; this.z = z; }
}

Vector3 ParseStruct(string str)
{
    var parts = str.Split(',');
    return new Vector3(
        float.Parse(parts[0]),
        float.Parse(parts[1]),
        float.Parse(parts[2])
    );
}

二、代码生成模板(以 C# 为例)

2.1 生成 C# 类

假设你有如下表头:

字段名 id name hp skills color pos
类型 int string int array_int enum struct

你可以用如下模板生成 C# 类:

public class {ClassName}
{
{Fields}
}

自动生成字段:

string GetCSharpType(string type)
{
    switch (type)
    {
        case "int": return "int";
        case "float": return "float";
        case "bool": return "bool";
        case "string": return "string";
        case "array_int": return "int[]";
        case "array_float": return "float[]";
        case "enum": return "Color"; // 假设enum名为Color
        case "struct": return "Vector3";
        default: return "string";
    }
}

StringBuilder sb = new StringBuilder();
sb.AppendLine($"public class {className}");
sb.AppendLine("{");
for (int i = 0; i < fieldNames.Count; i++)
{
    string type = GetCSharpType(fieldTypes[i]);
    sb.AppendLine($"    public {type} {fieldNames[i]};");
}
sb.AppendLine("}");
File.WriteAllText($"{outDir}/{className}.cs", sb.ToString());

2.2 生成 enum

收集所有 enum 字段的取值,自动生成 enum 代码:

// 假设所有Color列的值为Red, Blue, Green
public enum Color
{
    Red,
    Blue,
    Green
}

2.3 生成 struct

public struct Vector3
{
    public float x, y, z;
    public Vector3(float x, float y, float z) { this.x = x; this.y = y; this.z = z; }
}

三、Unity 集成(Editor 菜单与一键导出)

3.1 Editor 菜单

Editor 目录下新建 TableExportToolEditor.cs

using UnityEditor;
using UnityEngine;

public class TableExportToolEditor
{
    [MenuItem("Tools/TableExportTool/Export All")]
    public static void ExportAll()
    {
        // 1. 扫描表格目录
        // 2. 读取并解析表格
        // 3. 导出数据和代码
        // 4. 刷新AssetDatabase
        Debug.Log("表格导出完成!");
    }
}

3.2 导出到 Resources 或 AssetBundle

将导出的 JSON/二进制文件放到 Assets/Resources/Config/,运行时可用:

TextAsset ta = Resources.Load<TextAsset>("Config/Hero");
string json = ta.text;
var heroList = JsonUtility.FromJson<HeroListWrapper>(json);

3.3 支持热更

可在运行时从服务器下载新表,覆盖本地表,重新加载即可。


四、总结

  • 类型扩展:在类型转换和代码生成时支持 array_float、enum、struct 等,需在模板和解析函数中同步扩展。
  • 代码生成模板:用字符串模板+字段循环,自动生成 C# 类、enum、struct。
  • Unity 集成:用 Editor 菜单一键导出,导出到 Resources/AssetBundle,支持热更。

你可能感兴趣的:(游戏工具链,游戏)