Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Game Design Tools — 游戏策划配置工具

把策划维护的 Excel 配置表读进来,转成统一的中间格式,然后一方面导出成各引擎能用的代码,另一方面让 AI 能直接帮你查表、填表、校验。

这个项目结合了两类工具的定位:

  • 类似 GameConfig:把 Excel 导出成程序可用数据(多语言导出、表继承、多主键、增量发布)
  • 类似 gamedesign-skills:让 AI 理解项目,帮你设计、填表、查表、校验

核心理念

整个工具是三层结构,数据单向流动:

┌──────────────────────────────────────────┐
│ ① 表解析层(core/parser.ts)              │
│   Excel → 统一中间格式(schema + rows)   │
│   支持横表 / 纵表 / 继承 / 多主键         │
└──────────────────┬───────────────────────┘
                   │ 中间格式(内存)
     ┌─────────────┴─────────────┐
     ▼                           ▼
┌────────────┐           ┌────────────────┐
│ ② 导出层   │           │ ③ AI 层        │
│ adapters/  │           │ query/validate │
│ 中间格式 → │           │ /fill CLI      │
│ 各语言代码 │           │ (供 AI 调用)  │
└────────────┘           └────────────────┘

第一层和第二层是纯代码,不需要 AI,跑一次就出结果。第三层依赖第一层产出的数据,AI 不用读原始 Excel,读中间格式更快更准。

支持的语言和引擎

语言适配器

语言 ID 别名 输出目录 输出内容
typescript ts output/typescript/ 接口 + 常量数组(.ts)
csharp cs output/csharp/ 类 + 静态数据(.cs)
gdscript gd output/gdscript/ 类 + 常量表(.gd)
lua — output/lua/ 以主键为索引的表(.lua)
json — output/json/ 通用 JSON
tres godotres output/tres/ Godot Resource(.gd + .tres)

引擎映射

引擎 默认语言 说明
unity csharp Unity 用 C#
cocos typescript Cocos Creator 用 TypeScript
godot gdscript Godot 用 GDScript

--engine 会自动选默认语言。--engine 和 --lang 同时传时以 --lang 为准,比如 --engine godot --lang tres 就能导出 Godot Resource 格式。

字段类型到各语言的映射

schema 类型 TypeScript C# GDScript Lua
int number int int number
float number float float number
string string string String string
bool boolean bool bool boolean
enum 字符串联合类型 string String string
int[] / ref[] number[] int[] Array[int] table
float[] number[] float[] Array[float] table
string[] string[] string[] Array[String] table
ref number int int number
object Record<string, unknown> string(JSON) Dictionary table

环境要求

  • Node.js 18 或以上
  • 配置表是 .xlsx 格式

不依赖 Windows,不依赖 Python,Mac、Linux、Windows 都能跑。

安装

cd game-design-tools
npm i

依赖就一个 exceljs,用来读写 Excel。tsx 和 typescript 是开发依赖,用来跑和类型检查。

快速开始

# 生成一份示例数据,写到 knowledge/gamedata/game.xlsx
npm run sample

# 看看有哪些表
npm run list

# 导出到不同引擎 / 语言
npm run export -- --engine unity     # C#,输出到 output/csharp
npm run export -- --engine cocos     # TypeScript,输出到 output/typescript
npm run export -- --engine godot     # GDScript,输出到 output/gdscript
npm run export -- --lang lua         # Lua
npm run export -- --lang json        # JSON
npm run export -- --lang tres        # Godot Resource

导出后把 output 对应目录下的文件拷进引擎工程就行。

命令详解

所有命令都通过 npm script 调用,传参数时在命令后加 --,比如 npm run query -- --table Hero。

list — 列出所有表

npm run list

输出 JSON,每个表包含 name(表名)、comment(注释)、count(行数)。

query — 查询数据

npm run query -- --table Hero                        # 查整张表
npm run query -- --table Hero --key 1001             # 按主键查一行
npm run query -- --table SkillLevel --key skillId=1,level=2   # 复合主键
npm run query -- --refs Buff                         # 反查谁引用了 Buff
选项 说明
--table <表名> 要查询的表,必填(除非用 --refs)
--key <值> 主键值。单主键传标量;复合主键传 k=v,k=v 或 JSON 对象
--refs <表名> 反查引用关系,替代 --table

结果都是 JSON 输出,方便 AI 或脚本直接读。

validate — 校验完整性

npm run validate

检查三类问题:

  1. 主键空值或重复,复合主键按整个元组判重
  2. 引用完整性,ref 和 ref[] 指向的表要存在,值要能命中目标表主键
  3. 枚举合法性,enum 字段的值要在 enumValues 范围内

问题分 error 和 warning 两级,没问题就输出"校验通过"。

fill — 变更写回 Excel

先写一个 changes.json:

[
  { "table": "Hero", "key": 1001, "fields": { "attack": 1200 } },
  { "table": "Hero", "key": 1005, "fields": { "id": 1005, "name": "新英雄", "attack": 500 } },
  { "table": "SkillLevel", "key": { "skillId": 1, "level": 2 }, "fields": { "damage": 250 } }
]
npm run fill -- --input changes.json

每条变更的字段:

字段 说明
table 目标表名
key 主键值,用来定位行。单主键传标量,复合主键传对象
fields 要写入的字段和新值

规则是 key 能匹配到现有行就更新那行,匹配不到就追加新行,新行会自动补上主键字段。

数组字段在 JSON 里直接写数组就行,工具会自动按 arraySeparator 拼回 Excel 字符串。object 字段写对象,自动 JSON 序列化。

export — 导出代码

npm run export -- --engine unity
npm run export -- --lang tres
npm run export -- --engine unity --incremental true   # 增量,只导改过的表
npm run export -- --engine unity --out output/myconfig --namespace MyGame
选项 说明
--lang 语言,ts / cs / gd / lua / json / tres
--engine 引擎,unity / cocos / godot,自动选默认语言
--out <目录> 输出目录,默认 output/语言名
--incremental true 增量发布
--namespace C# 命名空间,默认 GameConfig

通用参数

所有命令都支持:

选项 说明 默认值
--schema <路径> schema 配置文件路径 config/schema.json
--data <目录> Excel 数据目录 knowledge/gamedata

增量发布

首次导出会在输出目录写一个 .manifest.json,记录每张表的内容哈希(SHA-256)。之后每次导出:

  • 哈希没变的表跳过,不重写文件
  • 哈希变了的表重新生成
  • 已经从 schema 删掉的表,清理它的旧输出文件

适合接 CI 或热更流程,只推送真正变动的数据。

接入你自己的项目

分三步。

第一步:定义表结构

编辑 config/schema.json,为每张表声明字段。结构如下:

{
  "arraySeparator": "|",           // 数组分隔符,默认 |
  "tables": [
    {
      "name": "Hero",              // 表名,要和 Excel sheet 名一致
      "comment": "英雄配置表",      // 注释,会进生成代码
      "primaryKey": ["id"],        // 主键,可多个字段
      "layout": "horizontal",      // 横表(默认)或 vertical 纵表
      "extends": "BaseHero",       // 表继承,父表名(可选)
      "fields": [
        { "name": "id", "type": "int", "comment": "英雄ID" },
        { "name": "roleType", "type": "enum", "enumValues": ["tank", "dps"] },
        { "name": "skillIds", "type": "int[]", "elementType": "int" },
        { "name": "passiveBuff", "type": "ref", "refTable": "Buff" },
        { "name": "isBoss", "type": "bool", "defaultValue": false }
      ]
    }
  ]
}

第二步:放置 Excel 数据

把 Excel 放进 knowledge/gamedata。一个 sheet 就是一张表,sheet 名要和 schema 的 name 一致,第一行是表头(字段名),第二行起是数据。没在 schema 里声明的列会被忽略。

第三步:运行

npm run validate        # 先校验,确认没有引用或主键错误
npm run export -- --engine unity   # 再导出

schema 字段说明

表级字段

字段 必填 说明
name 是 表名,和 Excel sheet 名一致
fields 是 字段定义数组
primaryKey 否 主键字段名数组,默认 ["id"]
comment 否 表注释
layout 否 horizontal(横表,默认)或 vertical(纵表)
extends 否 父表名,启用表继承

字段级字段

字段 必填 说明
name 是 字段名,和 Excel 表头一致
type 是 类型,见下面字段类型表
comment 否 字段注释
enumValues enum 时 枚举允许的值列表
refTable ref / ref[] 时 引用的目标表名
elementType 数组时 数组元素类型 int / float / string
defaultValue 否 空单元格的默认值
nullable 否 是否允许为空

字段类型

类型 说明 Excel 里的样子
int 整数 120
float 浮点数 0.05
string 字符串 亚瑟
bool 布尔,true/1/是/yes 都是真 0 或 1
enum 枚举,要配 enumValues tank
int[] 整数数组 1|2|3
float[] 浮点数组 0.5|1.0
string[] 字符串数组 战士|近战
ref 引用一条记录,要配 refTable 101
ref[] 引用多条记录 101|102
object JSON 对象 {"atk":120,"crit":0.15}

数组默认用竖线分隔,可以在 schema 顶层改 arraySeparator。ref 和 ref[] 会在 validate 时做引用完整性检查。object 在 Excel 里存 JSON 字符串,导出到 C# 也是 JSON 字符串,GDScript 里则是 Dictionary。

Excel 数据约定

横表(默认)第一行是字段名表头,每行一条记录:

| id   | name  | attack |
| 1001 | 亚瑟  | 120    |
| 1002 | 艾琳  | 800    |

纵表(layout 设为 vertical)第一列是字段名,每列一条记录:

| id     | 1001 | 1002 |
| name   | 亚瑟 | 艾琳 |
| attack | 120  | 800  |

空单元格取 defaultValue(如果声明了),否则是 null。整行全空的行会被跳过。

表继承

子表声明 extends 指向父表,就自动合并父表的所有字段,子表同名字段优先。子表的 Excel 里要包含父表的字段列加上自己的字段列。

{
  "name": "EliteHero",
  "extends": "Hero",
  "primaryKey": ["id"],
  "fields": [ { "name": "star", "type": "int" } ]
}

导出时 C# 和 TypeScript 会生成真正的继承(class EliteHero : Hero、interface EliteHero extends Hero),父表字段不重复声明。GDScript 和 Lua 会把字段直接展平。

多主键

primaryKey 可以写多个字段,比如 ["skillId", "level"]。各命令对复合主键的处理:

  • query 用 --key skillId=1,level=2,按全部主键字段匹配
  • validate 按整个元组判重、查空
  • fill 的 key 传对象 {"skillId":1,"level":2},按全部主键定位行
  • Lua 导出用下划线拼主键做索引,比如 SkillLevel["1_2"]

Windows 的 PowerShell 会丢掉参数里的双引号,所以复合主键建议用 k=v,k=v 这种写法,别用 JSON 对象。

Godot Resource 格式

--lang tres 每张表生成三个文件:

Hero.gd           行资源类,extends Resource,@export 字段
HeroTable.gd      容器类,@export var items: Array[Hero]
HeroTable.tres    数据资源,sub_resource 逐行加顶层 items

把整个输出目录放进 Godot 项目的 res:// 下就能加载。

让 AI 帮你干活

项目里带了一个 opencode 技能,位置在 .opencode/skills/gamedesign-tools/SKILL.md。重启 opencode 后,在项目里直接用自然语言说需求就行,比如:

  • 把英雄 1001 的攻击改成 1200
  • 查一下 Skill 表
  • 校验配置有没有引用错误
  • 导出成 Unity 代码

AI 会按技能里写好的流程去跑 query、fill、validate、export。技能文档里写清楚了所有命令和填表工作流,AI 会自动遵循。

目录结构

game-design-tools/
│
├── config/
│   └── schema.json              表结构定义,接入项目主要改这里
│
├── knowledge/
│   └── gamedata/                📥 输入:配置表 Excel,每 sheet 一张表
│
├── output/                      📤 输出:导出的代码,按语言分目录
│
├── src/
│   ├── index.ts                 CLI 入口,解析参数分发命令
│   │
│   ├── core/                    ⚙️ 核心逻辑,跟语言无关
│   │   ├── types.ts             中间格式类型定义
│   │   ├── schema.ts            加载 schema、解析继承
│   │   ├── values.ts            类型转换(Excel→值、值→Excel)
│   │   ├── parser.ts            Excel 解析成中间格式
│   │   ├── database.ts          扫描目录、构建配置库
│   │   ├── exporter.ts          导出编排、增量发布
│   │   ├── hash.ts              表内容哈希
│   │   ├── query.ts             查询
│   │   ├── validate.ts          校验
│   │   └── fill.ts              回写 Excel
│   │
│   └── adapters/                🧩 各语言适配器,加语言就加文件
│       ├── index.ts             适配器注册、引擎默认语言
│       ├── helpers.ts           公共工具
│       ├── typescript.ts
│       ├── csharp.ts
│       ├── gdscript.ts
│       ├── lua.ts
│       ├── json.ts
│       └── tres.ts
│
├── scripts/
│   ├── make-sample.ts           生成示例 Excel
│   └── test.ts                  端到端测试
│
└── .opencode/skills/
    └── gamedesign-tools/SKILL.md   AI 技能

数据流全景:

config/schema.json  ─┐
                     ├─→ database.ts(加载+继承)→ 中间格式 ConfigDatabase
knowledge/gamedata/*.xlsx ┘                          │
        ┌────────────────────────────┬──────────────┘
        ▼                            ▼
   exporter.ts(导出)          query/validate/fill(查询/校验/回写)
        │                            │
        ▼                            ▼
   adapters/* 各语言代码        JSON 输出 / 写回 Excel

扩展新语言

在 src/adapters 下新建一个文件,实现 LanguageAdapter 接口,然后在 index.ts 里注册就行。接口定义在 src/core/types.ts,参考 json.ts(最简单)或 typescript.ts(较完整)写。

import type { LanguageAdapter } from '../core/types';

export const myLangAdapter: LanguageAdapter = {
  id: 'mylang',                    // 唯一 ID,也是输出目录名
  name: 'My Language',
  extension: '.my',
  mapType(field) { /* 字段类型转语言类型 */ return ''; },
  mapValue(value, field) { /* 值转语言字面量 */ return ''; },
  generateTable(table, options) { /* 生成文件数组 */ return []; },
};

测试

npm run test

测试会临时生成一个 Excel,覆盖表继承、复合主键、引用校验、增量导出、回写这些场景。

常见问题

object 字段导出到 C# 是 JSON 字符串,因为 C# 没有通用动态类型,运行时自己反序列化。要强类型就单独建表用 ref 引用。

不支持 .xls 旧格式,只支持 .xlsx,旧文件在 Excel 里另存一下。

schema 不能省略,它是字段类型、引用、主键的唯一来源,AI 也靠它理解项目。

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages