主题
SCE 数据编辑器 Skill
选择宿主
按开发入口规则优先复用用户已打开目标项目的可视化编辑器,除非用户主动要求隔离;没有已打开的 GUI 或用户要求隔离时,AI 编辑数据、保存生成与构建优先 Headless,先检查 capability、项目状态和 tools/list。GUI 数据面板的 ui_* 上下文工具仍使用完整编辑器。GUI 和 Headless 不要同时写同一项目;下文的 GUI HTTP 辅助脚本不能替代 Headless 启动与能力检查。
配置生效与扩展字段
JSON 允许保存项目/编辑器的自定义辅助字段;生成器只生成实际声明的字段,未知字段静默跳过是预期行为,不要删除这些扩展内容或将它们当作无效数据。未知字段不会自动成为运行时 C# 属性。已声明字段的值无法生成而被注释,则检查 GDATA001、generationWarningCount 和结构化 diagnostics。增量诊断只覆盖本次处理的文件,完整审计可用 generateAll: true。
修改继承集合后核对本地、继承和有效值;新版设置工具返回 fieldState / fieldStates,不要把 reset 解释成清空继承数组。函数可以是常量或触发器函数引用;图形界面“新建函数...”可创建并绑定,JSON 没有 => 不代表不支持逻辑。
先记录安装版本与双端 API,再做引用、生成、编译和新局验证;build_start / debug_start 已包含保存和生成。详细流程见技能、AI 与表现:从配置到运行证据。
何时使用
当任务涉及以下内容时使用本 Skill:
- 创建、查询、修改或删除
editor/data/**/*.json里的 GameData 配置 - 在触发编辑器中定义自定义数编 Class,或在纯代码项目中使用
[GameDataCategory]/[GameDataNodeType<T,V>] - 扩展物品分类等枚举选项,并使其在图形化数据编辑器中可选
- 使用
data_*、gamedata_*、完整编辑器ui_*MCP 工具操作数据编辑器 - 处理
$id、$inherit、Link 字符串路径、继承覆盖、本地字段等数编机制 - 判断是在定义数编类型、创建编辑器条目,还是注册 runtime-only 条目
- 修改数据后需要同步
src/DataGenerated/**
先判断是在定义“类型”还是创建“条目”
| 用户诉求 | 维护入口 |
|---|---|
| 用现有字段再做一份单位、技能、配置等数据 | 数据编辑器 / editor/data 中创建条目 |
| 现有类型缺少项目需要的字段或专用行为,且要用图形化数据编辑器 | 先在触发编辑器定义 Class,并在属性面板“设置为数编类型” |
| 建立独立数据族,且要用图形化数据编辑器 | 先在触发编辑器定义 Class,并在属性面板“设置为数编分类” |
| 新增物品分类等枚举选项,且要在图形化数据编辑器中选择 | 在触发编辑器公共页新建预设值类型,并“继承”要扩展的预设值类型 |
| 项目明确采用纯代码类型定义 | 在 src/**/*.cs 手写对应 C# 特性 |
| 只在本局临时构造、不需要编辑器维护 | 在统一初始化路径创建 runtime-only GameData |
data_* 工具只能维护已经存在于 CLR/schema 中的类型、表和条目。gamedata_list_types 找不到目标类型时,不要通过未知 $type、额外 JSON 字段或随意选择一个通用配置类型来绕过;先完成类型 authoring、代码生成与编译发现。
自定义类型的权威契约见 GameData 数据驱动系统。本 Skill 只保留 AI 执行闭环。
自定义类型执行闭环
- 先用
gamedata_list_types/gamedata_get_type_schema确认内置或项目已有类型确实无法表达需求。 - 如果用户要使用图形化数据编辑器,先切到触发编辑器:
- 在 “共用(Common)” 环境用 “类定义” 新建普通 Class,并添加字段属性
- 独立根分类在 “属性设置” 勾选 “设置为数编分类”
- 已有分类的子类型勾选 “设置为数编类型”,依次选择 “节点分类”(根分类 T)和 “节点父类”(直接父类 V)
- Class 事先不能已有其它父类或名为
Link的成员,也不要同时设置成分类和节点类型
- 在触发编辑器先 “保存”,再执行 “生成代码文件”。确认
src/TriggerGenerated/{env}.cs中生成了partial class与对应的GameDataCategoryAttribute/GameDataNodeTypeAttribute<T,V>;不要手改生成文件。 - 同时编译 Client-Debug 和 Server-Debug,让 source generator 生成并验证类型;共享数编类型不能只存在于单端环境。
- 让编辑器重新加载最新项目程序集,再用
gamedata_list_types和gamedata_get_type_schema确认类型与字段已经可见。 - 此后才用
data_create_table/data_create_entry创建 JSON-backed 表和条目,最后调用data_save_and_generate。
如果用户明确选择纯代码开发,则不要继续上述图形化闭环:在具名 namespace 的 src/**/*.cs 中手写 [GameDataCategory] / [GameDataNodeType<T,V>] 的 public partial class,并在统一 GameData 初始化路径用 new GameData...(link) 注册具体条目。不要显式继承生成器负责的基类,不要手写 Link 构造器或生成接口,也不要再为同一条目创建 JSON-backed 定义。
如果当前 AI 工具只有 data_*,没有触发编辑器属性面板或能等价修改触发模型的能力,不要退化为手写 editor/trigger JSON,也不要擅自切换到纯代码路线;明确请用户在触发编辑器完成上述两个开关之一,再继续创建条目。触发器工具的保存和生成边界见 触发器编辑器 Skill。
优先选择 MCP
可扩展枚举与图形化选项
当用户要扩展 ItemCategory 等可扩展枚举,并在数据编辑器的选项中使用时,先在触发编辑器公共页(Common)声明预设值类型,将其**“继承”**设置为目标预设值类型,再添加预设值。公共页让两端共用声明;保存后的权威源是触发器 JSON。仅手写 [EnumExtension] C# 并编译成功,不能替代图形化声明。
“继承”对应 EnumExtension.Extends;“是否可被继承”对应 Extendable,后者不能替代继承目标。通过 trigger_create_preset 导入时按 触发器 MCP Skill 创建并 trigger_save,确认生成代码仍包含目标 Extends,双端编译、加载最新声明后再用 data_* 选择新增值。不要用未知分类字符串、注释或手改 DataGenerated 掩盖声明缺失。图形化操作说明见 枚举扩展。
公共模板与基础定义
创建样例单位、技能、Buff 或物品时,先用 data_list_templates 查 GameSparkCore 的适用模板并读取实际字段。通过 $inherit 继承,保留样例自己的模型、技能链和数值覆盖;基础生命值、单位属性、伤害类型等引用 GameSparkCore 的声明。通用能力缺少模板时应在公共库补充;不要从其它样例私有模板复制一套基础定义。该优先策略不限制项目自定义类型或专用数据。
模板表的 tableType 为 ScopeDataTemplate,普通实例表为 ScopeData。旧参数 Template 在新版 MCP 中作为兼容别名转换。创建后用 data_list_templates 验证可发现性,并保留编辑器生成的稳定 $id。
迁移继承后检查集合合并语义:模板已有的 Health/Mana 不要在本地 VitalProperties 再添加一次;保留有意覆盖,必要时使用正式删除/覆盖表达式。先 data_save_and_generate 加 validate;游戏项目需要运行验证时用正常 debug_start 编译双端并检查新局,依赖库或只验证编译时走下面的纯构建流程。不要手工改 Metadata、EntryInfo 或 DataGenerated 来掩盖源数据问题。
依赖库数据生成与编译
在 GUI 或 Headless 中打开目标库,分别用 editor_get_context 或 headless_get_project_state 确认路径,再发现 build_start 的实际 schema。调用后使用返回的 build_id 查询 build_wait / build_status,以 succeeded 终态确认生成、双端 Debug 编译和 AppBundle 部署完成;失败时按同一 ID 读取 build_diagnostics,修复源数据、触发器或代码再重试。build_start_timeout 时先用返回的 operation_id 查询状态,避免重复任务。
此流程不启动游戏。依赖库直接调试会返回 dependency_library_requires_test_project;行为测试改用引用它的游戏项目,或已配置测试地图的菜单路线。不要用 debug_start_no_compile 绕过这个限制。仅需保存和生成数据时使用 data_save_and_generate。详细流程见只生成与编译。
如果编辑器或 MCP Host 正在运行,优先用 MCP:
ui_*读取当前数据编辑器上下文;这需要完整 Editor MCPdata_*读写 DataManager 表、条目、字段、继承状态gamedata_*查询 GameData 类型 schema,或生成src/DataGenerated
Invoke-SceMcp.ps1 是 Trigger/Data 兼容 HTTP MCP 单次 tools/call 入口,可以调用 data_*、gamedata_*、trigger_* 等可由 TriggerMcpHost fallback 支持的工具。脚本在地图工程根的 ai/tools/ 下时可自动推断工程根;如果从 SDK 模板 docs/ai/tools/ 运行,需要传 -ProjectRoot 指向地图工程根。
如果要调用 ui_*,或需要 editor_get_context、tools/list schema 发现和完整编辑器诊断,使用 Invoke-SceEditorMcp.ps1:
powershell
.\ai\tools\Invoke-SceEditorMcp.ps1 -Context -Pretty
.\ai\tools\Invoke-SceEditorMcp.ps1 -Tool ui_get_editor_state -ArgumentsJson '{}' -Pretty推荐调用方式:写一个临时 JSON,包含 baseUrl、tool、arguments,用 -RequestJsonPath 调脚本,最后删除临时文件。
powershell
$MapRoot = "D:\YourSceMap"
$McpScript = Join-Path $MapRoot 'ai\tools\Invoke-SceMcp.ps1'
$TempRequest = Join-Path $env:TEMP ("sce-data-mcp-" + [Guid]::NewGuid().ToString("n") + ".json")
$PowerShellExe = Get-Command pwsh -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty Source
if ([string]::IsNullOrWhiteSpace($PowerShellExe)) {
$PowerShellExe = Get-Command powershell -ErrorAction Stop | Select-Object -First 1 -ExpandProperty Source
}
@'
{ "baseUrl": "http://127.0.0.1:8765/", "tool": "data_list_tables", "arguments": {} }
'@ | Set-Content -LiteralPath $TempRequest -Encoding utf8
try {
& $PowerShellExe -NoLogo -NoProfile -ExecutionPolicy Bypass -File $McpScript -RequestJsonPath $TempRequest
} finally {
if (Test-Path -LiteralPath $TempRequest) { Remove-Item -LiteralPath $TempRequest -Force }
}成功返回时先看外层 result.isError。业务结果通常在 result.content[0].text,多数是 JSON 字符串。写操作不要并行;连续修改时等上一个工具返回后再调用下一个。
自然语言一键做完整地图
MCP 工具必须保持通用。即使用户说“做一张某某玩法地图”,也不要新增玩法专用工具;AI 应该把自然语言拆成通用 plan,再调用通用 MCP:
- 读取上下文:
ui_get_editor_state、data_list_tables、gamedata_list_types、trigger_get_api_schema - 数据侧一键创建:
workflow_create_map_from_plan - 触发侧创建逻辑:
trigger_create_folder、trigger_create_class、trigger_create_function、trigger_create_trigger - 保存与生成:优先
data_save_and_generate;需要拆步时用data_save、gamedata_generate_code、trigger_save - 项目校验:
gamedata_validate_project、trigger_validate_project
自然语言只负责描述目标玩法;MCP 参数里用通用字段表达:
contentRoot:本玩法的数据目录名,例如AutoBattle1v1tables:需要的 GameData 表规格entries:单位、技能、配置、GameMode、生成器等条目规格links/attachments:条目之间的字段引用和追加挂接gameMode:玩法入口配置save、generateCode、validate:是否保存、生成和校验
示例骨架:
json
{
"tool": "workflow_create_map_from_plan",
"arguments": {
"contentRoot": "AutoBattle1v1",
"entries": [
{
"kind": "unit",
"entryName": "Footman",
"displayName": "Footman",
"stats": { "maxHp": 420, "attack": 18, "moveSpeed": 270 }
},
{
"kind": "spawner",
"entryName": "FootmanSpawner",
"displayName": "Footman Spawner",
"spawnEntries": ["Footman"],
"spawnIntervalSeconds": 15,
"spawnCount": 2
},
{
"kind": "config",
"entryName": "EconomyConfig",
"category": "Config",
"fields": { "InitialGold": 500, "IncomeIntervalSeconds": 10, "IncomeGold": 50 }
}
],
"gameMode": {
"entryName": "AutoBattleMode",
"displayName": "Auto Battle 1v1",
"players": [{ "id": 1 }, { "id": 2 }],
"teams": [{ "id": 1 }, { "id": 2 }]
},
"save": true,
"generateCode": true,
"validate": true
}
}如果某个玩法需要“兵营、商店、刷怪点、波次、经济”等概念,优先用 workflow_create_spawner、普通 kind: "config" 条目和 links 表达。不要把玩法名写进 MCP 工具名。
工具速查
| 类别 | 工具 |
|---|---|
| UI 上下文 | ui_get_editor_state、ui_get_current_table、ui_get_selected_entry、ui_get_selected_field |
| 表与条目查询 | data_list_tables、data_get_table、data_list_entries、data_get_entry |
| 表与条目创建 | data_create_table、data_create_entry |
| 模板与批量创建 | data_list_templates、data_create_from_template |
| 字段级修改 | data_get_field、data_set_field、data_set_fields、data_insert_field、data_move_field、data_remove_field |
| 继承与本地覆盖 | data_get_inherit、data_get_local_data、data_get_base_data、data_get_field_status、data_reset_field、data_reset_entry |
| GameData 类型与生成 | gamedata_list_types、gamedata_get_type_schema、gamedata_get_generated_symbols、gamedata_generate_code |
| Link、资源与引用 | data_list_link_candidates、data_find_references、data_resolve_entry_links、data_validate_links、resource_search |
| 项目校验 | gamedata_validate_entry、gamedata_validate_project |
| 制作人工作流 | workflow_create_content_folder、workflow_create_unit、workflow_create_ability、workflow_attach_ability_to_unit、workflow_create_spawner、workflow_create_game_mode、workflow_create_map_from_plan |
| 触发器配合 | trigger_get_api_schema、trigger_create_folder、trigger_create_class、trigger_create_function、trigger_create_trigger、trigger_save、trigger_validate_project |
| 删除与移动 | data_delete_entry、data_delete_table、data_move_table |
| 保存与生成 | data_save、data_save_and_generate、gamedata_generate_code |
data_update_entry 是危险工具:它会用完整 JSON 覆盖条目的本地数据。普通修改优先使用 data_set_field 或 data_set_fields。
data_save_and_generate 是修改数编后的首选收口工具:它会保存当前 DataManager 状态、可选校验项目、生成 src/DataGenerated,并返回保存状态、校验摘要、生成结果和文件变更摘要。完整编辑器已加载项目但数据编辑器面板未打开时,工具会自动加载当前项目的 DataManager;如果编辑器没有加载任何项目,会以 no_project_loaded 明确失败。只有需要先预览内存态生成、或刻意不保存源数据时,才单独调用 gamedata_generate_code 并设置 saveData。
标准工作流
1. 用户说“当前选中”或“这里”
ui_get_editor_state- 需要条目时调用
ui_get_selected_entry - 需要字段时调用
ui_get_selected_field - 再用返回的
entryId/fieldPath调data_get_entry、data_get_field_status或字段级写入工具
如果 editorOpen 为 false,说明当前会话拿不到数据编辑器 UI;改用 data_list_tables / data_list_entries 根据路径和类型定位。
2. 修改已有条目字段
data_get_entry读取目标条目,确认metaType、$inherit与当前值gamedata_get_type_schema查询该metaType的权威字段 schema- 对继承字段先用
data_get_field_status判断是local、inherited还是default - 小改用
data_set_field,多字段改动用data_set_fields - 运行时需要更新
ScopeData.*时调用data_save_and_generate - 只需要保存源数据、不需要刷新运行时代码时调用
data_save
3. 创建新条目
data_list_tables找到目标表,或用data_get_table确认表路径和类型gamedata_list_types/gamedata_get_type_schema确认要创建的 GameData 类型和字段- 找一个相近条目或模板:
data_list_entries后data_get_entry - 用
data_create_entry创建,entryData只放必要的$type、$inherit和少量初始字段 - 用
data_set_fields补齐本地覆盖字段 - 需要刷新运行时代码时调用
data_save_and_generate;否则调用data_save
不要为了复刻模板而把继承来的字段全部写成本地字段;这会破坏模板继承的维护价值。
4. 修改 Link 字段
普通 Link 字段在 JSON 中是字符串路径,不是 {"$ref": ...}。
gamedata_get_type_schema确认字段是否是 link,或看字段 schema 里的jsonType: "link"/linkTargetTypedata_list_link_candidates传entryIdOrPath和fieldPath获取合法候选- 从候选的
value中选择要写入的字符串 - 用
data_set_field或data_set_fields写入 - 若要删除或替换目标条目,先对目标调用
data_find_references
常见 Link 字符串:
- 同一蓝图文件内引用其他节点:
$this.EntryName - 同库跨蓝图引用:相对逻辑路径或
$GameDataRule.DefaultDisplayInfo.Root - 跨库稳定引用:
$id.EntryName
5. 处理继承与本地覆盖
data_get_inherit查看继承链data_get_base_data查看继承来的基础数据data_get_local_data查看本地覆盖data_get_field_status判断具体字段来源- 想恢复继承值时用
data_reset_field - 想清空全部本地覆盖时才用
data_reset_entry
data_remove_field 是删除本地字段;如果字段有继承值,通常应使用 data_reset_field。
6. 删除或移动前先查引用
删除条目、删除表、移动表或替换 Link 目标前,先运行:
text
data_find_references -> 确认 referenceCount 为 0 或逐项处理引用 -> 再删除/移动 -> data_save_and_generate?data_find_references 是字符串引用扫描,能发现常见 entryId、$this.EntryName、路径后缀和表路径引用。复杂脚本引用仍需要配合代码搜索。
类型定义与条目来源边界
数编类型与数编条目是两层来源:
类型结构来自触发编辑器定义生成的
src/TriggerGenerated/**,或纯代码项目维护的src/**/*.cs;数据编辑器和 JSON 不能动态发明 CLR 类型静态数编条目有两种合法来源,应与所选类型 authoring 路线成套使用:
- 图形化路线:
editor/data/**源数据,包括直接编辑 JSON 和通过data_*MCP 修改 - 纯代码路线:
src/**/*.cs代码注册,例如OnGameDataInitialization中new GameDataUnit(...)
- 图形化路线:
同一个静态 GameData 条目只能选择一种来源。不要把 JSON-backed 条目做成薄壳,再在代码里对 ScopeData.GameDataXxx.*.Data 做静态补丁。定义条目的 CLR 类型与用 JSON 创建该类型的条目并不冲突;前者定义 schema,后者提供具体值。
src/DataGenerated/** 只是生成投影,用来确认 ScopeData.* 名称和生成结果,不是主要维护入口。
编辑器派生元数据文件
editor/data/** 里并不是所有 JSON 都是可手工维护的源数据。AI 修改数编时只把业务蓝图文件当作源数据,例如 ScopeData/**/SomeData.json 或 ScopeDataTemplate/**/SomeTemplate.json。
Metadata.json是编辑器生成的文件级元数据,记录蓝图文件 ID、类型和文件引用依赖等索引信息。EntryInfo.json是编辑器生成的条目级缓存,记录$hash、Name、DisplayName、Icon等注册缓存字段,供数据编辑器列表、代码生成和检索使用。- 这些文件反映源数据的派生状态,不是新增条目、改字段、修 link 的 authoring 入口。
- 不要为了“补齐”“整理”“修复引用”而手动编辑、复制或重写
Metadata.json/EntryInfo.json。 - 如果这些文件在
data_save、data_save_and_generate、编辑器保存或gamedata_generate_code后产生 diff,通常应视为生成结果;如果是 AI 手改造成的 diff,应还原后让编辑器/MCP 重新保存生成。
$id 规则
- 这里的
$id指 JSON 顶层蓝图文件 ID,不是 MCP 的tableId或entryId $id标识整个蓝图文件,不是 Entry Name- AI 直接创建新的 JSON 文件且不确定
$id格式时,优先省略$id - 编辑器会在加载/保存时自动补合法且唯一的
$id - 已存在的
$id不要轻易修改,因为其他蓝图文件可能通过$id.EntryName引用它
推荐顺序:
- 先创建新文件,不写
$id - 让编辑器加载或保存一次,自动补全
$id - 再读取实际
$id - 最后再填写其他蓝图文件里的跨蓝图引用
直接写 JSON 时的最低约束
只有 MCP 不可用、需要批量离线修改、或用户明确要求直接改 JSON 时,才直接编辑 editor/data/**/*.json。
- 一个 JSON 文件对应一个蓝图文件;文件内有
Root、OtherEntry等 Entry Root、OtherEntry等键名是 Entry Name- 同一蓝图内引用优先
$this.EntryName - 同库跨蓝图引用优先相对逻辑路径
- 跨库稳定引用优先
$id.EntryName $inherit也是字符串路径Metadata.json、EntryInfo.json、src/DataGenerated/**是派生结果,不要手动维护
正确顺序通常是:修改源数据 -> 让编辑器或 MCP 保存 -> 运行现有生成链刷新派生物;MCP 场景优先用 data_save_and_generate 一步完成保存与生成。
常见错误
- 新建 JSON 时手写了错误格式的
$id - 修改已有
$id,却没有同步更新$id.EntryName引用 - 把
data_get_entry返回的展示性元数据当作源字段写回 - 直接用
data_update_entry全量覆盖,误删本地字段或继承关系 - 给 Link 字段写
{"$ref": ...},而不是写字符串路径 - 从
DataGenerated反推错误模式,对.Data做静态 patch - schema 中没有类型或字段时,硬写未知
$type/ 额外 JSON 字段 - 纯代码路线忘记给自定义类型加
partial,或手写了生成器负责的父类和构造器 - 同一个条目一部分放在 JSON,一部分又放进
OnGameDataInitialization