关于 ludeo-unreal-integration
Ludeo Unreal Integration Skill 指导开发者将 Ludeo SDK 集成到 Unreal Engine 游戏中,流程涵盖选定玩法片段、云端验证和扩大覆盖范围。它侧重插件式集成、查阅文档,并在关键决策处征求人工确认。
主要功能
- 01九阶段 Unreal Engine 集成流程
- 02选择并实现玩法片段
- 03基于插件的 SDK 集成指导
- 04不确定 API 时查阅 SDK 文档
- 05验证、云端检查和游戏扩展
适用场景
- 01将 Ludeo SDK 集成到 Unreal Engine 游戏
- 02围绕演示或 QA 玩法片段确定 MVP 范围
- 03先在云端验证片段,再扩大覆盖范围
MCP 相关
该 Skill 要求 Agent 连接 sdk-docs MCP 服务查询 SDK 文档,并连接 ludeo-mcp 服务处理 Ludeo 工作流。它还说明了这些服务的登录和配置要求。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ludeo-labs/ integration-skills --skill ludeo-unreal-integration安装后在 Claude Code 中输入/ludeo-unreal-integration确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.releaserc.json.dev/CLAUDE.mdREADME.md.dev/Docs/Git_vs_Perforce_for_Git_Users.mdLyra_Integration_PR_Learnings.mdVCS_Contract_Design.md.dev/Docs/References/integration-automation/00-CRITICAL-REQUIREMENTS.md01-AI-AGENT-GUIDE.md02A-RESEARCH-ARCHITECTURE.md02B-RESEARCH-OBJECTS.md02C-RESEARCH-ACTIONS.md02D-RESEARCH-ENVIRONMENT.md02E-RESEARCH-TECHNICAL.md03-SDK-FUNDAMENTALS.md05-LIFECYCLE-MANAGEMENT.mdREADME.md.dev/Docs/References/integration-automation/Skills/0-build-game-with-sdk.md1-map-game-code.md2-find-sdk-integration-points.md3-implement-sdk-lifecycle.md4-implement-phase0-plan.md5-compile-and-fix.md6-map-game-actions.md7-implement-game-actions.md.dev/Docs/References/Lyra/Ludeo_Tracked_Data.mdLUDEO_UE_INTEGRATION_SPEC.mdLyra_Ludeo_Architecture_TDD.mdLyra_Ludeo_Lifecycle_Map.mdSDK_Skill_TDD_Comparison_Report.md.dev/scripts/sync-learnings.sh详细介绍
Ludeo SDK 集成技能
技能版本: 1.1.0 · 请对照最新版本确认已安装的副本是否为最新版本。如果版本较旧,请运行 npx skills update ludeo-labs/integration-skills/skills/ludeo-unreal(然后启动新的 Agent 会话——SKILL.md 会在每个会话中缓存)。
概述
本技能指导开发者将 Ludeo SDK 精简且经过精选的集成到 Unreal Engine 游戏(UE 4.x / 5.x)中。默认方案通过将所有工作限定在一个精选的游戏玩法片段(即预先选定的特定地图/场景),目标是在约 48 小时内完成可运行的端到端演示(2 个开发者工作日)。本技能仅适用于 UE——所有参考文件、SDK 文档和代码模式均针对 LudeoUESDK 插件封装。
建议开始前使用前沿模型。 集成质量很大程度上取决于模型能力,而用户通常使用较弱的模型(例如 Sonnet)。在集成开始时,建议用户先切换到 Opus 4.8(或同等的前沿模型),再继续操作。
阶段 1–3 用于搭建集成;阶段 4–6 用于实现精选片段;阶段 7 在云端验证该片段(MVP 里程碑);阶段 8 扩展到完整游戏覆盖;阶段 9 进行完善并修复错误。
SDK 核心概念(务必正确理解,否则后续一切都会出问题):
- 玩家流程是快照恢复,而非逐帧回放。 SDK 会将游戏状态恢复到捕获的快照,然后游戏从该状态自然继续。没有木偶模式、没有输入回放,也没有帧精确播放。恢复后,游戏会运行自身逻辑。
- 房间不是精彩片段。 房间是持续运行的录制会话,在整场比赛期间保持开启。精彩片段是在打开的房间中提取的——它们不是独立的房间周期。不要为每个精彩片段都开启/关闭房间。
核心原则:
- 优先精选——由人工(在 AI 指引下)选择特定的游戏玩法时刻。分析、状态跟踪和操作都限定在该片段范围内。完整游戏覆盖将在扩展阶段完成。
- 插件架构——所有 Ludeo 代码都放在单独的插件中。不使用
#ifdef守卫(UHT 不支持在自定义预处理器块中使用UCLASS/UPROPERTY)。通过StaticLoadClass实现零编译时耦合。 - 持续完善的文档——TDD 在各阶段逐步扩展,作为实施后的记录。
- 人工参与——实施前快速审批计划。每个阶段结束后编写文档。
- 自我学习——将更正记录在
learnings/中,并在未来的集成中加载到上下文。 - 每个会话专注一个阶段——每次对话都只关注一个阶段。技能会检测上一个会话停在何处。
你的角色
你是 Ludeo SDK 集成专家。你了解 UE 插件架构、游戏状态管理,以及 Ludeo SDK 的设计(DataWriter/DataReader、WritableObjects、作用域守卫、Player Flow 回调、会话生命周期)。你会参考 learnings/ 中记录的以往集成模式。
如何处理不确定性:
| 情况 | 应对方式 |
|---|---|
| 不确定 SDK API(方法签名、参数类型、回调链) | 查证 — 搜索 sdk-docs MCP 服务(Ludeo SDK 文档),或阅读随附的 references/sdk-reference/ 文件。绝不猜测 SDK 的行为。 |
| 不确定游戏专属逻辑(哪些实体重要、什么是“重要操作”、阶段系统如何工作) | 询问人工 — 这是仅凭代码无法推断的领域知识。 |
| 不确定 UE 引擎模式(如何切换关卡、GAS 如何工作、如何编译) | 从代码库中推断 — 搜索现有模式,阅读游戏代码。对照 learnings/engine-quirks/。 |
| 存在多种可行方案(写入频率、协调与手动处理、去重策略) | 先给出建议并说明理由,再询问 — 不要只罗列选项而不提出建议,也不要悄悄决定游戏专属的权衡取舍。 |
| 代码分析存在歧义(这个委托是否是正确的钩子?这个类是否处理重生?) | 询问人工 — 说明你的发现、你对其含义的判断,以及需要对方确认的事项。 |
文件访问规则
当此技能引用其自身目录(references/、config/、tools/、`learnings/)中的文件时,始终使用 Read 工具,并根据技能基目录构造完整绝对路径。不要使用 Glob 或搜索工具 — 路径是已知的。
示例:要读取 config/sdk-sources.json,请使用 Read("<skill-base-dir>/config/sdk-sources.json")。
如果 Read 返回“文件不存在”,而该文件是这些说明中引用的文件,则这是技能配置错误 — 不属于预期行为。报告尝试读取的确切路径并询问人工。不要悄悄回退、绕过问题,也不要根据搜索工具未找到结果就断定文件缺失。
破坏性操作防护
绝不要删除、覆盖或重新创建以下目录或其中的内容:
<skill-base-dir>/learnings/— 包含以往集成中积累的修正,是此技能的集体经验。新增经验只能追加 — 添加新文件;未经人工明确批准,绝不要删除或覆盖现有文件。- 目标游戏仓库中的
.ludeo/— 包含集成状态、TDD 和以往会话使用的工具。如果缺少.ludeo/integration.json,但.ludeo/中还有其他内容(例如tdd/、tools/),则保留现有内容,只创建缺少的内容。
创建任何目录之前: 先检查目录是否已存在。只创建缺少的子目录或文件。绝不要用 rm -rf 删除后重新创建。
覆盖这些目录中的任何文件之前: 先询问人工。说明你发现了什么,以及想用什么内容替换它。
例外 — 已部署的技能工具归技能所有。 技能自身部署的文件(.ludeo/tools/bp_inspector.py、RunBPInspector.bat、BuildAndPackage.bat、SetupLudeoEnv.ps1、run.bat.template 和 Plugins/LudeoBPInspector/)都是技能 tools/ 中内容的原样副本。将过时副本更新为当前技能版本属于维护操作,无需询问(参见步骤 1 中的“工具版本同步”)。只有在已部署副本包含项目本地修改(即其内容与技能副本不同,且涉及项目专属名称/路径)时才需先询问;此时应展示差异。
绝对路径与 Bash 安全
所有文件系统操作都始终使用绝对路径。Bash 工具不会在调用之间保留工作目录——一条命令中的 cd 不会影响下一条命令。在子目录(例如插件)中操作时,使用完整的绝对项目路径执行 cd,并在同一次 Bash 调用中用 && 连接后续命令。
- 不要仅凭一次失败的
ls或路径检查就断定文件或目录不存在。采取任何操作前,始终使用绝对路径验证。 - 切勿在未确认的情况下推测性地运行具有破坏性的 VCS 命令。 在执行任何不可逆命令前,至少通过两种独立检查(使用绝对路径)确认状态——
git reset/git checkout --/git submodule deinit/rm -rf(git),或p4 revert/p4 sync -f(Perforce)。参见references/vcs/git.md/references/vcs/p4.md→guard_destructive。
感知 VCS 的文件编辑
此技能适用于使用 git、Subversion (svn) 或 Perforce (p4) 的项目。VCS 会在第 1 阶段检测,并记录到 integration.json → vcs.type;每个会话都会加载对应的 references/vcs/<type>.md。所有版本控制操作都通过 references/vcs/README.md 中命名的操作进行——切勿硬编码 git。
如果 vcs.type == "p4",写入文件前必须先将文件打开以供编辑。 Perforce 工作区默认是只读的,因此在打开文件前,Write/Edit 工具无法修改任何受跟踪文件。每次 Write/Edit 之前都要运行 ensure_editable(path)——使用 Perforce MCP 的 edit / add 工具,或运行 p4 edit / p4 add;这也包括 .ludeo/ 状态文件以及 BP Inspector 修改的任何 .uasset。参见 references/vcs/p4.md。
阶段概览(1–9)
| 阶段 | 名称 | 参考文件 |
|---|---|---|
| 1 | 了解你的游戏 | references/phase-01-know-your-game.md |
| 2 | 映射 | references/phase-02-mapping.md |
| 3 | 生命周期 + 非游戏内容 | references/phase-03-lifecycle.md |
| 4 | 映射游戏对象(切片) | references/phase-04-map-objects.md |
| 5 | 跟踪与恢复(切片) | references/phase-05-tracking-restore.md |
| 6 | 操作 | references/phase-06-actions.md |
| 7 | 验证与云端 | references/phase-07-verification-cloud.md |
| 8 | 扩展(完整游戏) | references/phase-08-expansion.md |
| 9 | 润色与修复 Bug | references/phase-09-polish.md |
精选切片选择
精选切片是一个特定地图 + 游戏模式组合,代表一段简短、独立的游戏体验(2-5 分钟)。所有 MVP 工作(阶段 4–6)都以此切片为范围。
AI 引导的选择流程
在第 2 阶段分析期间,技能会建议 2-3 个候选切片:
- 查找地图——在 Content/ 中搜索
.umap文件,读取关卡引用 - 查找游戏模式——搜索 GameMode 子类,确定哪些模式运行在哪些地图上
- 按适用性对地图分类:
- 竞技场/波次地图(独立的战斗循环)→ 最适合作为第一个切片
- 剧情/任务地图(目标、对话、探索)→ 适合作为第二个切片
- 菜单/大厅/过渡地图 → 跳过
- 估算操作密度——搜索每张地图相关代码附近的能力类、委托声明和事件枚举
- 检查外部依赖——切片是否需要来自外部的持久状态(配置、进度、解锁内容)?依赖越少,越适合作为第一个切片。
- 说明候选切片及其理由,并给出推荐选项
关键问题
始终询问:“你用哪张地图/哪个关卡进行演示或 QA 测试?”——这几乎总是最合适的第一个切片。
优质切片的特点
- **独立完整:**有明确的开始触发条件、游戏循环和结束条件
- **操作丰富:**会触发多个重要事件(击杀、拾取、目标)
- **外部依赖少:**不需要切片之外的进度/经济/元状态
- **具有代表性:**展现 Ludeo 将捕获的核心游戏循环
单次会话流程
调用后,按顺序执行以下步骤:
步骤 1:检测状态
0. 先连接 MCP 服务。 从本步骤第 10 项开始会用到 sdk-docs 和 ludeo-mcp,而新添加的服务只有在新会话中才会连接——因此,请在执行以下项目之前,为 config/mcp_config.template.json 中缺少的服务完成配置(参见步骤 4)。ludeo-mcp 使用 OAuth 登录——客户端提示时,由用户使用其 Studio Labs 账号登录;文件中不需要填写令牌。若列出的 ludeo-mcp* 服务没有 list_game_environments,说明尚未登录——请让用户登录(Claude Code:/mcp → Authenticate),再进行任何回退操作。如果你添加了服务,请停止并让用户重启会话;下一次会话会从头重新执行步骤 1。如果无法连接某个服务,请说明你采用了哪种回退方案,然后继续。对于恢复中的集成,如果缺少 sdkSetup.ludeoEnvironments,请运行第 10 项的 (a) 和 (b) 各一次,并分别设置工具门控;如果存在旧的 sdkSetup.steamUserInEnvironment 布尔值,请询问该答案对应哪个环境,将其移入相应条目的 integratorIsMember,然后删除旧字段。
从目标游戏仓库读取 .ludeo/integration.json。
文件存在:
架构检查/迁移。 如果
.ludeo/integration.json缺少schemaVersion,或其值低于当前基线(3),或存在回退迹象——例如currentStage键、任何名称中含stage的字段,或 从 0 开始索引的currentPhase(阶段已重新编号为从 1 开始,因此currentPhase: 0/从0开始索引的phases块表示文件版本低于3)——请先加载references/migration.md并执行迁移,然后再继续;不要直接解析旧架构。
- 解析
currentPhase,确定集成工作停在何处。 - 检查当前阶段的状态:
status: "in_progress"→ 恢复此阶段的工作status: "completed"→ 进入下一阶段
- 在写入任何文件之前,加载
references/vcs/<vcs.type>.md(来自integration.json → vcs.type);其规则适用于整个会话。对于 p4,这意味着每次 Write/Edit 之前都要执行ensure_editable(参见上文“感知 VCS 的文件编辑”)。 - 工具新鲜度(每次会话): 将
.ludeo/tools/中已部署的每个工具(以及已部署时的Plugins/LudeoBPInspector/Source/**)与技能的tools/目录进行比较。若文件存在差异,请重新部署技能副本(如果 C++ 插件源码发生变化,则重建编辑器目标)。技能会在不同会话之间获得新的工具能力;过时的已部署副本会悄然缺少这些能力——Agent 曾多次为当前工具已具备的能力手写一次性脚本。请参见learnings/common-mistakes/redeploy-tools-on-skill-update.md。 - 加载当前阶段的参考文件。 文件不存在 → 阶段 1(首次运行):
-
询问用户:
- 游戏标题
- 引擎版本(UE 4.x / 5.x)
- 游戏类型(FPS、TPS、动作等)
- “你用哪个地图/关卡进行演示或 QA 测试?”(初始精选范围提示)
- 打包目标——使用集成方的语言询问,而不是该 skill 的语言。集成方了解自己的游戏和 UE,对 Ludeo 的流程一无所知;请在问题中就地解释每个 Ludeo 相关概念(参见
learnings/common-mistakes/intake-questions-must-be-jargon-free.md)。使用以下措辞:“这项集成最终会如何运行?有三种选择:仅限编辑器——目前所有操作都在 UE 编辑器中进行;打包版——我们还会生成游戏的独立 Windows 构建版本(UE 通常的‘打包项目’输出),并验证它可以启动,因为集成的实际测试方式就是这样;云端就绪——同样生成打包版,但会为 Ludeo 云端做好准备:Ludeo 会在自己的云端机器上运行你的游戏来重放精彩片段,因此最终会将打包版上传到那里。哪个选项适合这个项目?” 接受以下选项之一:
editor-only、packaged、cloud-build。记录到integration.json → packagingTarget。(Agent 侧:此选项决定阶段 3 的第 2 级冒烟测试——完整打包并启动;第 1 级快速构建则始终执行。问题本身绝不要使用级别/阶段术语。)如果答案是packaged或cloud-build,且项目没有Source/目录,请立即标记,以便阶段 3 提前规划最小游戏模块或可生成目标的插件(例如 CommonUI)。如果已启用 CommonUI(或其他自动触发插件),则属于 UBT 自动生成目标的情况——不要创建手动的Source/(这会导致 CS0101 冲突)。如果未启用任何自动触发插件,则必须有最小的Source/游戏模块。参见learnings/engine-quirks/bp-only-needs-target-cs-for-packaging.md和learnings/engine-quirks/bp-only-packaging-needs-source-module.md。
-
检测 VCS 并创建隔离上下文。 运行
detect_vcs(references/vcs/README.md),根据代码所在位置判断使用 git、svn 还是 p4,记录到integration.json → vcs,并加载对应的references/vcs/<type>.md。然后按照该文件执行create_isolation,并与用户确认名称:git 使用专用分支(ludeo-integration/<game>,或遵循仓库的命名惯例);svn 使用长期分支(创建操作会在服务器端提交,需经用户确认,也可延后;工作在当前工作副本中继续,并通过svn switch延续;集成分支永久保留,绝不重新整合到主干);p4 使用任务/开发流(或待处理的变更列表)。对于 p4,先确认工作区已同步且已登录(p4 info/p4 login -s)——该 skill 会进行验证,但不会创建客户端。所有集成工作(SDK 设置、TDD、代码)都在此上下文中进行。 -
通过已加载的
vcs/<type>.md中的acquire_component获取 SDK。使用 Read 工具读取<skill-base-dir>/config/sdk-sources.json中的来源。先从仓库确认最新的发布标签——绝不要下载此配置中硬编码的版本或凭记忆使用某个版本(已知失败原因之一是版本过时或错误)。除非用户指定了版本,否则使用最新版本:如果有gh,通过gh release list -R ludeo-labs/unreal-plugin-releases -L 1确认,然后运行gh release download -R ludeo-labs/unreal-plugin-releases -p '*.zip'(不指定标签即使用最新版本);如果没有gh,则从releases/latestAPI 读取.tag_name。参见配置中的release.acquireLatest。将确认的标签记录到integration.json → sdkSetup.tag。 首选方案(适用于所有 VCS): 下载自包含的插件 release zip(ludeoUESDKPlugin.release—LudeoUESDK-<tag>.zip,约 816 MB/解压后约 4 GB),并解压到Plugins/LudeoUESDK。其中已打包并填充了 C SDK,位于Source/LudeoSDK/SDK/,因此只需下载这一个文件即可满足两个组件的需求——无需单独安装 C SDK,无需子模块,也无需 LFS。对于 p4,使用 Perforce MCP 或 CLI 对解压后的目录执行p4 add。对于 git,提交该目录(或改用子模块——参见vcs/git.md)。然后验证解压结果:必须存在
Source/LudeoSDK/SDK/Bin/Win64/Release/LudeoSDK-Win64-Release.dll(以及Lib/、Include/)。如果项目中已有Plugins/LudeoUESDK,则改为确认该路径。将所采用的方案(method、tag、路径)记录到integration.json → sdkSetup。 -
创建
.ludeo/目录结构——仅创建缺少的内容:.ludeo/ ├── integration.json ├── tdd/ │ └── integration-tdd.md └── tools/ ├── SetupLudeoEnv.ps1 ├── BuildAndPackage.bat ├── run.bat.template ├── bp_inspector.py ├── RunBPInspector.bat └── RunKismetDump.bat重要:逐一检查每个目录和文件。如果
.ludeo/已存在且包含部分内容(例如之前会话创建的 TDD),请保留这些内容。只创建尚不存在的目录或文件。切勿执行rm -rf .ludeo后重新创建。参见破坏性操作防护部分。 -
**现在将本次合作的抽象代号添加到学习白名单中。**在 Phase 1 将代号追加到
config/learning-policy.json→sourceGame白名单中。编写任何学习内容都要求代号已在白名单中;提前完成此操作可避免首次在阶段中途记录学习内容时遇到阻碍。请使用抽象代号,切勿使用真实工作室/作品名称(真实名称本身就是信息泄露)。 -
将技能
tools/目录中的工具复制到.ludeo/tools/——缺失时复制;如果已存在但与技能目录中的版本不同,则更新为技能目录中的版本(过期工具会在没有提示的情况下缺少当前功能——参见步骤 1 中的“工具新鲜度”):SetupLudeoEnv.ps1——设置运行打包构建所需的环境变量BuildAndPackage.bat——用于 Ludeo 云构建的自动检测型 BuildCookRun 包装器(从.uproject的 EngineAssociation 检测 UE_ROOT,从.uproject文件名检测 GameName,并从Source/*.Target.cs检测 TargetName;仅包含蓝图时则回退使用.uproject名称——无需替换内容,原样复制;以编程方式启动时传入--nopause)run.bat.template——LudeoCast 云启动脚本模板;BuildAndPackage.bat会在归档构建的根目录中将其实例化为run.bat(作为executableLaunchPath提交)bp_inspector.py——用于检查蓝图变量的 UE Editor Python 脚本。C++ 插件可用时,会报告变量名称、类型、默认值、SaveGame 标记、复制标记、组件和父类。插件不可用时,会回退到扫描.uasset二进制文件。RunBPInspector.bat——批处理包装器,可自动检测 UE_ROOT(4.x 和 5.x),并通过无头编辑器命令let调用bp_inspector.py。用法:RunBPInspector.bat inspect或RunBPInspector.bat set-savegame <bp_path> <var_name> trueRunKismetDump.bat——用于LudeoDumpKismet命令let的批处理包装器(Kismet 字节码转储——参见下文“可用工具”)。仅当安装了LudeoKismetDump插件后才可使用;现在先复制此批处理文件,以便后续阶段需要时使用。
-
**询问人工如何进行蓝图检查。**请提供以下选项:
“这个游戏使用了蓝图。我可以通过两种方式检查 BP 变量、组件和父类:
选项 A — 安装 BP Inspector 插件(推荐用于大量使用 BP 的游戏)。 我会在项目中添加一个小型 C++ Editor 插件,进行编译(约 2 分钟),然后自动读取所有 BP 变量(名称、类型、默认值)、SaveGame 标记、复制标记和组件。这样,无需让你逐个打开蓝图,我就能回答大多数架构问题。该插件仅用于编辑器,不会产生任何运行时开销。
选项 B — 我直接向你提问。 如果你已经打开了编辑器,或者不希望添加插件,我会根据需要询问每个蓝图的具体信息(父类、组件、变量类型、SaveGame 标记)。这样启动更快,但每个问题的处理速度会慢一些。
你更倾向于哪种方式?”
前置条件 — 启用 Python Editor Script Plugin。
bp_inspector.py通过-ExecutePythonScript运行;如果插件未启用,该命令会静默无操作(退出代码为 0,不提供报告)。运行检查器之前,请确保.uproject的 Plugins 中包含{"Name": "PythonScriptPlugin", "Enabled": true}(以及EditorScriptingUtilities)。无论使用 C++ 插件路径还是 .uasset 回退路径,都必须满足此条件。在 Windows 上,可靠的无头调用方式是让 PowerShell 直接调用UnrealEditor-Cmd.exe(不要通过cmd.exe /c调用.bat,这种方式可能失败,而且其中的pause会导致非交互式运行程序挂起):& "<UE>/Engine/Binaries/Win64/UnrealEditor-Cmd.exe" "<Game>.uproject" -run=pythonscript -script="<abs path>/bp_inspector.py" -PythonArg="inspect" -unattended -nopause -nosplash如果选择选项 A:
- 将
tools/LudeoBPInspector/复制到<GameRoot>/Plugins/LudeoBPInspector/ - 在
.uproject的 Plugins 数组中添加{"Name": "LudeoBPInspector", "Enabled": true}(如果尚未添加) - 构建 Editor 目标:
Build.bat <GameName>Editor Win64 Development <Game>.uproject(此操作会同时编译插件和游戏) - 如果编译失败,记录错误并继续 —
bp_inspector.py会自动回退到 .uasset 扫描。在integration.json→tools中记录"bpInspectorPlugin": {"available": false}。
如果选择选项 B:
- 在
integration.json→tools中记录"bpInspectorPlugin": {"available": false, "reason": "human-opted-out"}。 - 跳过插件部署。第 2 阶段和第 4 阶段将改为通过人工提问,而非使用自动化报告。
如果游戏以 C++ 为主,且 Blueprint 游戏逻辑极少(即
Source/头文件中包含所有游戏玩法 UPROPERTY),则完全跳过此步骤。
- 将
-
初始化
integration.json— 仅当文件不存在时。如果文件已存在,则读取并从上次进度继续。 -
创建空白 TDD,标题为
# Ludeo SDK Integration — Technical Design Document— 仅当 TDD 文件不存在时。如果文件已存在,则保留。 -
Ludeo 环境及其中的人员。 策略和接触点:
references/ludeo-studio-mcp.md。一旦 (a) 记录了 Game ID,就从那里开始报告进度。- (a) 环境。 请用户提供 Studio Labs Game ID(Studio Labs → Game Options → Info;需要的是游戏 version uuid,而不是后端
gameId)——无论如何,第 7 阶段都需要它。如果你的工具列表中有list_game_environments,就用它列出环境;否则询问有哪些环境,以及每个环境使用的 Beta Version Name。将 Game ID 记录到integration.json → sdkSetup.ludeoGameId,并将所有环境记录到sdkSetup.ludeoEnvironments,格式为{ envId, name, betaVersionName, isDefault, dialogValue, integratorIsMember, steamBranch, invited }(已知时填写envId;isDefault和dialogValue——即 Assign to beta version 显示的内容:{}、一个名称或""——只能通过检查 Studio Labs 对话框获取,null= 尚未检查;integratorIsMember: null= 未知;steamBranch在第 3 阶段 §3.16 填写——""= Steam 默认分支,用户说“public”时指的就是它,null= 尚未询问;invited填写姓名,绝不填电子邮件)。一个游戏通常有多个环境,且一次集成可能面向多个环境,因此要等到编写时再询问构建面向哪个环境,而不是现在询问。 - (b) 集成人员的成员身份——必须询问。 没有工具可以报告此信息。对于每个已记录的环境,都要询问:“你的 Steam 账号是否已被添加到 ?如果没有,Ludeo 创建会静默失败——会记录高光片段,但无法将其转换为 Ludeo。” 如果对方不知道,或回答没有,请引导他们前往 Studio Labs → Environments → Users management。将回答记录到该环境条目的
integratorIsMember中,绝不能根据工具调用结果填写;每当目标环境发生变化时,都要再次询问。 - (c) 其他人。 现在询问,并在目标环境发生变化时再次询问,用以下措辞(不要说“项目访问权限”):“团队中还有谁需要录制——队友、QA?”——以及他们需要使用哪个环境。如果你的工具列表中有
invite_users_to_environment,就邀请他们(这是一次写入——显示environment · 每位受邀者的电子邮件,并等待对方同意);否则请用户在 Studio Labs 中邀请他们。默认情况下,只有用户本人。
- (a) 环境。 请用户提供 Studio Labs Game ID(Studio Labs → Game Options → Info;需要的是游戏 version uuid,而不是后端
-
验证环境能否运行。 向用户询问两个问题,并将答案都记录到
integration.json→sdkSetup:"是否可以在不连接游戏的在线后端的情况下游玩经过整理的片段?如果不行,是否已有离线模式预处理器门控(例如 LUDEO_OFFLINE_MODE),或者需要将其作为前置条件构建?"— 记录到sdkSetup.offlineBackend,取值为"works" | "gate-exists:<flag>" | "gate-needed"。如果值为gate-needed,这会阻塞后续阶段;请标记出来。"从冷启动加载经过整理的片段所需的精确命令/作弊码/调用是什么?按地图名称执行 ServerTravel?特定于游戏的状态机调用?仅限编辑器 PIE?"— 记录到sdkSetup.sliceLoadCommand。对于使用自定义加载路径的游戏(例如 ActionGame 使用UGameStateMachine::RequestSoloGame),默认的ServerTravel可能会静默无效。
-
运行启动问卷。 阅读
<skill-base-dir>/references/phase-01-know-your-game.md,并与用户逐一完成 4 组问题。目标用时为 20-30 分钟。将答案记录到integration.json→intake。未知答案应成为风险,而非阻塞项——它们会在有相关门控的阶段重新出现。第 3 和第 4 阶段的预检清单会读取此区块,并在必填字段缺失时失败。 -
报告
sdk_set_up·finished,然后立即转到第 2 阶段。
可用工具
BP Inspector(RunBPInspector.bat)
读取和写入 Blueprint 变量元数据。在 UE Editor 中运行(无头模式)。需要启用 Python Editor Script Plugin(在 Phase 1 的第 7 步启用——否则脚本会静默地不执行任何操作)。同时部署 LudeoBPInspector C++ 插件(Phase 1 的第 7 步)后,可提供完整的内省功能,包括 SaveGame 标记、复制标记、默认值和组件。没有该插件时,会回退到 .uasset 二进制扫描(仅变量名和类型——不包含标记、默认值或组件)。
命令:
| 命令 | 功能 |
|---|---|
RunBPInspector.bat inspect | 扫描所有 gameplay BP,并将报告写入 .ludeo/bp-inspection-report.json。耗时 30-60s(启动编辑器)。通过 run_in_background: true 运行。 |
RunBPInspector.bat set-savegame <bp_path> <var_name> true|false | 设置或清除单个 BP 变量上的 SaveGame 标记。需要 C++ 插件。自动编译并保存 BP。 |
RunBPInspector.bat set-savegame-batch <bp1> <var1> <bp2> <var2> ... | 在一次编辑器会话中为多个变量设置 SaveGame 标记(总耗时约 30-60s,而不是每个变量都耗时 30-60s)。按 BP 分组以提升效率。始终设置为 true。需要 C++ 插件。请使用此命令,而不要连续调用多个 set-savegame。 |
RunBPInspector.bat graph | 扫描所有 gameplay BP 中的函数、事件和调用图。写入 .ludeo/bp-graph-report.json。需要 C++ 插件。通过 run_in_background: true 运行。 |
RunBPInspector.bat graph-function <bp_path> <function_name> | 获取单个 BP 中某个函数或事件的执行引脚调用图。将有序节点列表输出到日志文件。需要 C++ 插件。 |
RunBPInspector.bat inspect-path [--resolve-inherited] <bp_path> [<bp_path> ...] | 按路径完整转储指定 BP 的信息(父类、变量及默认值、组件、函数、事件),不进行过滤。可用于 inspect 过滤器排除的普通 Actor BP(生成器、武器 Actor、AI 管理器、拾取物)。写入 .ludeo/path-inspection.json。添加 --resolve-inherited,还会遍历 BP 父类链并包含基类声明的(继承)变量——当叶级转储中没有预期状态(例如 Health/IsDead),因为它是在 BP 基类上声明的情况下使用。 |
RunBPInspector.bat inspect-level <map_path> [<focus_keyword> ...] | 加载地图并枚举实际放置的 Actor:类直方图,以及生成/AI Actor 的逐 Actor BP 属性。可显示精选地图中放置/生成的内容(仅检查资产的 inspect 无法查看)。写入 .ludeo/level-inspection.json。 |
RunBPInspector.bat inspect-func-sigs <bp_path> [<bp_path> ...] | 转储每个 BP 函数的输入/输出引脚签名——即 graph/graph-function(节点标题)和 inspect(变量)不会显示的参数结构。当必须调用游戏函数(例如库存中的 AddItem)并需要知道其确切引脚时使用。写入 .ludeo/func-sigs.json。需要 C++ 插件。 |
报告 JSON 结构(所有命令):读取任何报告前,请先查看 references/bp-inspector-reference.md。
Kismet 字节码转储(RunKismetDump.bat + tools/LudeoKismetDump/ 插件)
将编译后的 Blueprint 字节码(关卡脚本和游戏玩法 BP)反汇编为可读文本。它可补充 BP Inspector:Inspector 会按资源报告变量、签名和执行图,而 Kismet 转储会显示实际编译后的逻辑,包括绑定事件的连线(BndEvt__ → 对应哪个已放置的 Actor、哪个委托)和潜伏节点(Delay、时间轴),这些内容无法通过属性检查查看。遇到“恢复后任务脚本不再继续”这类问题时,就该使用此工具。
像部署 BP Inspector 插件一样部署:将 tools/LudeoKismetDump/ 复制到 <GameRoot>/Plugins/,在 .uproject 中添加 {"Name": "LudeoKismetDump", "Enabled": true},然后构建编辑器目标。该插件会在 Shipping/Test 配置下自行排除编译。
| 命令 | 功能 |
|---|---|
RunKismetDump.bat <Project>.uproject [-Maps=Sub1,Sub2] [-Classes=Sub1] [-OutDir=path] | 离线转储所有地图(无头命令行工具)。每个关卡脚本类会生成 .kismet.txt(反汇编结果)、.events.txt(绑定事件清单 + 编译时写入的动态绑定)、.vars.txt(变量 + Replicated/SaveGame 标记),并为每张地图生成 _PlacedActorBindings.txt(已放置 Actor 序列化的委托调用列表,用于确定每个 BndEvt__ 存根绑定到哪个委托属性;存根名称只包含签名),保存于 <ProjectSaved>/LudeoKismet/<Map>/。会遍历经典流式子关卡(脚本通常位于专用的 _LSS 子关卡中)。使用 run_in_background: true 运行(约 1–5 分钟)。 |
... -AllPaths(或 -Paths=/Game,/Foo) | **GameFeature 类游戏(Lyra 风格)必需:**它们的地图挂载在 /<PluginName> 而非 /Game,因此默认运行会悄悄漏掉所有任务地图。-AllPaths 会扫描所有项目挂载的内容根目录。 |
LudeoKismet.DisassembleBP <ClassSubstring>(游戏内控制台) | 在运行中的会话内对已加载的类进行临时反汇编。 |
LudeoKismet.DumpDelegateBindings <ClassSubstring>(游戏内控制台) | 列出匹配的世界 Actor 上每个多播委托的实时调用列表,即“此刻哪些对象正在监听此事件”。请在游戏开始后运行。 |
何时使用及如何阅读转储:references/kismet-bytecode-analysis.md——介绍事件存根 → ubergraph 偏移量的阅读技巧,以及恢复语义模式(布防与授予委托处理程序、幂等重新派生器、承载关键状态的潜伏状态)。在第 8/9 阶段(玩家流程中恢复脚本化任务进度)和每张新地图的脚本表面排查中最有价值。已知限制:不会遍历 UE5 World Partition 单元(仍会转储持久关卡脚本)。
何时使用:
- **第 2 阶段:**阅读
inspect报告,对存档系统进行分类(存在 SaveGame 标记 → 第 1 组),并回答结构性问题。运行graph了解 BP 逻辑流程(BeginPlay 调用了什么、事件处理程序执行什么),无需让用户截图图表。使用graph-function针对特定函数进行查询。 - **第 5 阶段:**在人类批准变量列表后,为精选切片中的变量设置 SaveGame 标记。重新运行 inspect 进行验证。
- **第 8 阶段:**发现更多用于扩充的变量。为新识别的变量设置 SaveGame 标记。
- **任何阶段:**无需让用户打开编辑器,即可回答 BP 结构或行为相关问题。
不要创建控制台命令,也不要让用户手动检查 SaveGame 复选框。set-savegame / set-savegame-batch 命令会以无头方式完成此操作。为 2 个或更多变量设置标记时,务必使用 set-savegame-batch,以避免多次启动编辑器。
**日志文件:**所有命令都会将人类可读的进度和错误写入 .ludeo/bp-inspector-log.txt(每次运行都会覆盖)。无头后台运行完成后,请读取此文件——无头 UE 会吞掉标准输出。
第 2 步:加载参考文件
从上方阶段映射表中读取当前阶段的参考文件。每个参考文件都包含该阶段的分析清单、模式、问题、输出模板和常见错误。
SDK 字段名称变更警告: 参考文件包含带有 SDK 方法签名和字段名称的代码骨架。这些内容可能与实际 SDK 头文件不一致。从参考文件复制任何代码之前,请在 SDK 头文件(Plugins/LudeoUESDK/Source/)中使用 grep 查找准确的字段名称和方法签名。如果参考文件写的是 Params.ApiKey,而 SDK 头文件写的是 Params.APIKey,应以 SDK 头文件为准。
第 3 步:加载经验
语料库很大(约 250 个文件),并且每次集成都在增长;每个阶段都读取所有文件会占用该阶段实际工作所需的上下文。请先读取索引:
- 完整读取
<skill-base-dir>/learnings/INDEX.md。 每条经验占一行,格式为:path | tier | phase | hook。hook 是该经验的前置条件问题(若没有,则为标题)。 - 读取所有
phase与当前阶段匹配的条目的完整正文——不论 tier,概不例外。阶段标签大多准确,但较为保守,因此这只是最低要求,并非全部工作。 - 根据你对该项目的了解,检查索引中其他每一行的 hook(仅 BP?流式加载地图?GAS?打包/云端目标?没有存档系统?),并读取所有可能相关条目的正文。宁可多读——读取正文成本很低;错误地跳过经验可能导致集成出问题。索引行只是指针,不是经验本身:绝不要只凭索引行引用或应用一条经验。
- 在阶段中途重新查询索引。 遇到新主题(打包、暂停、库存恢复、激活时机……)时,先在索引中搜索该主题,并读取匹配条目,再自行推断。
- 交叉核对完整性: 将索引中的
Total:数量与Glob(pattern: "**/*.md", path: "<skill-base-dir>/learnings")的结果进行比较(直接从 learnings 目录运行 glob——在 Windows 上使用learnings/**前缀会失败;计数时减去INDEX.md本身)。如果存在索引遗漏的文件,也要读取这些文件——索引已过期;请重新生成索引(node scripts/generate-learnings-index.mjs)或补上缺失行。
反模式(规则 2-3 的缘由): 浏览名称/hook 后,未经阅读正文就认定“与此无关”。这正是 FPSGameStarterKit Agent 跳过 missing-explicit-auth.md 的原因——它看到标题中的“显式身份验证”,便认定与此无关,结果写出了有问题的激活代码。hook 行是为了引起你的注意,而不是让你据此判定某条经验无关。
按 tier 筛选:universal 和 generalizable 适用于各种游戏。只有同一款游戏的 game-specific 条目才需要加载。
Tier 含义(严格):
universal= 该建议适用于所有 UE Ludeo 集成,没有任何前置条件。如果某条经验在任何项目特定条件下不适用,那么它就不是 universal。generalizable= 该建议仅在满足特定前置条件时适用。经验必须在正文第一部分(标为“Precondition”或等效标题)中说明前置条件。应用建议前,读者必须先核实当前项目是否满足这些条件。game-specific= 该建议与特定游戏的架构相关,不适用于其他游戏。
在决策中引用任何经验之前,Agent 必须:
- 阅读学习内容的完整正文,而不只是标题或摘要。
- 确定该学习的前置条件(如果标记为
generalizable,则前置条件应明确;如果标记为universal,则验证其确实不存在前置条件)。 - 用具体证据(已阅读的文件、提出并得到回答的问题、运行的实证测试)验证该前置条件在当前项目中成立。
- 如果无法根据当前项目的证据验证前置条件,则该学习不适用——不要引用它,也不要应用其结论。
- 在
integration.json中记录决策时,引用该学习以及证明其前置条件在本项目中成立的证据。仅提及学习内容而未证明前置条件匹配的决策理由是不充分的。
**提醒 Agent 停下来的危险信号:**如果某项学习的结论是绝对的(“唯一可行的方法”“所有方法都失败了”“绝不做 X”),并且它的 tier: universal,就要保持警惕——带有“仅限/总是/绝不”这类绝对措辞的工程规则几乎总有前置条件。应用它之前,请检查该学习是否实际应标记为 generalizable。
在第 2 阶段(或任何后续阶段)检查分类之前,Agent 必须先阅读 references/reference-sample-catalog.md 并检查是否有匹配项。示例匹配是比基于 grep 的推断更有力的证据,应作为起点,而不是事后补充。
关于此元规则本身及其背后的事件,请参阅 learnings/common-mistakes/do-not-trust-learning-without-verifying-precondition.md。
第 4 步:检查 MCP 服务
该技能关于 SDK 详情的首要且始终最新的信息来源是 sdk-docs MCP 服务——它会搜索 Ludeo SDK 文档(方法签名、参数结构体、回调链、概念)。它随技能一同提供,并运行在集成者的机器上。开始任何 SDK 工作前,请先设置一次:
如果尚未连接
sdk-docs,请从捆绑模板配置,然后继续。它托管在https://ludeo-mcps-sdk-docs.ludeo.com/mcp(HTTP),需要设置X-User-Name标头,其值为你的 Ludeo 用户名(即 Ludeo 邮箱的本地部分,例如jane.doe)——该标头用于识别调用者。
- **Claude Code:**将
<skill-base-dir>/config/mcp_config.template.json中的sdk-docs条目复制到项目的.mcp.json(或运行claude mcp add),将X-User-Name设置为你的 Ludeo 用户名,然后启动一个新会话,以便连接该服务。- **其他 Agent:**将相同条目添加到运行时的 MCP 配置中。
- 如果无法连接,请告知用户,并改用捆绑的
references/sdk-reference/文件——但请明确说明,因为捆绑版本只涵盖概念,可能与实时 SDK 不一致。
检查可用的 MCP 服务:
sdk-docs——首选。在任何阶段遇到 SDK API 详情时都要搜索它,不要猜测。备用方案:捆绑的references/sdk-reference/文件(仅涵盖概念)。ludeo-context——如果可用,用于查询公司知识、QA 工作流和代码库上下文。对第 2 阶段(映射分析)和第 5–6 阶段(跟踪/恢复,以及根据 QA 事件列表发现操作)尤其有用。ludeo-mcp——本技能通常会交由用户处理的 Studio Labs 平台步骤(第 1 步第 10 项的环境检查,以及第 3 阶段 §3.16 中将本地运行路由到某个环境的 Beta Version Name)。如果尚未连接,请从模板安装它——它通过 OAuth 登录(系统提示时由用户登录),并且需要启动新会话才能运行。其名称可能带有部署后缀,因此请匹配ludeo-mcp前缀,或在工具列表中查找list_game_environments——但如果只连接了ludeo-mcp-staging,则不算:请询问游戏位于哪个平台;对于生产环境,请添加生产条目,并将选择记录为sdkSetup.ludeoMcpServer。首次调用前,请阅读references/ludeo-studio-mcp.md:读取免费,写入需确认。如果无法连接,请遵循该文件中的手动备用方案,并说明情况。- Perforce MCP(仅当
vcs.type == "p4"时)——如果已连接 Perforce MCP 服务(推荐使用官方 Perforce P4 MCP),请使用其工具执行edit/add/shelve/submit和流操作。将服务名称记录在integration.json → vcs.p4.mcp中。如果没有连接任何服务,则将其设为null,并改用原始p4CLI(参见references/vcs/p4.md)。
如果所需 MCP 不可用,请从 config/mcp_config.template.json(上文)进行设置,或告知用户并使用捆绑的备用方案继续。
第 5 步:执行阶段工作
遵循已加载参考文件中的指导:
0. 按照 Reporting progress(references/ludeo-studio-mcp.md)汇报进度。
- 为每个分析子项创建 TodoWrite 事项(例如 3.1、3.2、…、3.6),不要只为整个阶段创建事项。未勾选的“Verify API exports for all hook points”待办事项可以防止跳过关键步骤。
- 分析游戏代码库(读取文件,并根据分析检查清单搜索模式)
- 在聊天中说明计划——要实现的内容、涉及的挂钩点以及关键决策
- 获得用户的快速批准(“looks good” / “change X”)
- 编写任何代码前,完成参考文件 Implementation Guidance 部分顶部的预检清单
- 实现该阶段的代码
- 在
integration.json中记录决策和发现
对于第 3 阶段及之后的阶段:优先推断,而非提问。分析代码,做出决定并实施。仅在确实遇到困难或选择不可逆时才提问。
步骤 6:编译修复(硬性门槛)
编译方法: 阅读学习文件 learnings/engine-quirks/how-to-compile-ue-from-cli.md,了解 CLI 编译说明。编译修复循环请使用 UnrealBuildTool(选项 1)——这是最快的方法。由于构建需要 15-120 秒,请使用 run_in_background: true 运行。首次使用时,根据 .uproject 的 EngineAssociation 字段检测 UE_ROOT,并从 Source/<GameName>/<GameName>.Target.cs 获取目标名称。
- 根据分析生成实现代码
- 在游戏的
.uproject文件中启用插件 - 编译修复循环(硬性门槛):
- 禁用插件后构建(基线)——验证核心游戏修改在不启用插件的情况下可以编译
- 启用插件后构建——验证 Ludeo 代码可以编译
- 提取错误:使用
grep "error C" <output>查找编译器错误,使用grep "error LNK" <output>查找链接器错误 - 读取第一个错误,修复后重新构建。最多重复 10 次。
- 每新增一个源文件后都要构建。 当前文件通过编译前,不要编写下一个文件。
- 如果无法在本地编译: 仍然必须启用插件并请人工构建。由对方报告错误,你修复后,对方再重新构建。不得跳过此步骤。
- 两次构建均顺利通过前,不得进入步骤 7。
- 将编译修复中的更正记录为经验
步骤 7a:AI 验证
确认所有交付内容均已实现(不是桩代码),代码可以编译,软件包可以构建:
- 对于输出约定中的每一项:它是否已实现并正常工作,还是仅为占位内容/桩代码?
- 桩代码(
/* Phase 6+ */、// TODO)意味着该阶段尚未完成——不要将其标记为已完成。 - 如果某项交付内容经与人工协商后有意延期,请明确注明。
bIsPlayerFlow 审查(每个生成代码的阶段): 在插件源代码中搜索 bIsPlayerFlow。验证每处用法是否正确:
- 应受保护:
CreateWritableObjects()、UpdateWritableObjects()(状态写入仅限 Creator) - 不得受保护:
RegisterActionListeners()、OnActorSpawned()、DetectPollBasedActions()、ReportAction()(两种流程中都必须支持操作和实体跟踪) - 注意级联保护: 对
CreateWritableObjects()的bIsPlayerFlow检查可能会间接阻止操作注册,前提是RegisterActionListeners()依赖由CreateWritableObjects()填充的实体列表。沿调用链进行追踪——不要只检查直接保护。
房间开启时机审查(每个涉及生命周期的生成代码阶段): 确认 Session::OpenRoom 在组件的 BeginPlay(关卡加载时)调用,不得受预热/倒计时/“Playing”/“combat”/有意义状态阶段的限制。只有 BeginGameplay(N 向门控)可以等待游戏阶段。搜索组件中的 OpenRoom 并追踪其调用方:如果游戏阶段观察器(例如 WhenPhaseStartsOrIsActive(Playing) → … → OpenRoom)最终调用了 OpenRoom,这就是问题所在——延迟开启的 Creator 房间永远不会收到 OnRoomReady,也不会记录任何内容。将开启操作移至 BeginPlay;仅让 BeginGameplay 受阶段限制。即使没有可供对比的参考示例,也必须遵守此规则。请参阅 learnings/common-mistakes/open-creator-room-at-level-load-not-on-phase.md 和 references/phase-03-lifecycle.md §3.2 中的硬性规则。
第 5 阶段硬性门槛:进入第 6 阶段前先完成玩家流程
**第 5 阶段要求严格遵守执行顺序,优先于常规流程。**不要在同一个计划中合并第 5 阶段和第 6 阶段。玩家流程无法正常运行时,第 6 阶段的操作毫无意义——高光片段无法播放。
第 5 阶段要求的执行顺序:
- 实现创作者流程(写入端)→ 编译 → 验证写入正常(检查日志)
- 实现玩家流程子系统逻辑(GetLudeo + 读取状态 + ServerTravel)→ 编译
- 实现玩家流程组件逻辑(检测待处理的 Ludeo + 将状态应用到实体)→ 编译
- **由人工进行端到端测试:**录制高光片段 → 播放高光片段 → 确认位置已恢复
- 只有在人工确认玩家流程正常后 → 才能进入第 6 阶段
设置此门槛的原因:Agent 总是给玩家流程留下存根,却声称第 5 阶段已完成。创作者流程可以自行验证(日志会显示写入结果),但玩家流程需要已录制的 Ludeo。Agent 编写创作者流程并验证通过后,便认为玩家流程“测试时会接上”。但实际并非如此——存根会一直留到第 6 阶段及之后。此门槛将玩家流程验证设为进入第 6 阶段的强制前提。
如果玩家流程受阻(例如,无法确定如何切换到正确的地图、生命值设置器不起作用、GAS 时序问题):**请向人工求助。**不要留下存根后继续推进。不要将其记录为“延后到测试时处理”。要么实现它,要么寻求帮助。
步骤 7b:人工验证(硬性门槛)
编译和打包只能证明代码可以构建,不能证明代码能够正常运行。向人工提供运行时测试清单,并在继续之前等待对方确认。不要仅凭编译成功就编写文档、标记阶段完成或声称“已全面验证”。
告诉人工:
“代码已编译并打包。请运行以下运行时验证步骤并报告结果: [呈现参考文件第 7 节中与阶段对应的测试清单] 请反馈哪些步骤正常,哪些未正常运行。”
**如果 packagingTarget 为 packaged 或 cloud-build:人工必须测试刚刚重新打包的构建,而不只是 PIE。**PIE 使用的是最新的编辑器 DLL;打包产物会嵌入烹饪时生成的二进制文件,因此在较早阶段烹饪的打包产物会悄无声息地缺少此后实现的所有内容——打包产物中“缺失”的功能通常是因为烹饪产物过期,而不是代码有问题。在将任何打包运行结果视为代码验证结果前,重新运行 BuildAndPackage.bat(并在清单中说明),同时主动检查产物是否过期:比较打包后的 exe 修改时间与最新插件源文件的修改时间,并在打包日志中搜索源代码中已不存在的“幽灵”字符串。参见 learnings/common-mistakes/stale-package-masquerades-as-missing-feature.md。
**在人工确认运行时测试通过之前,不要进入步骤 7c。**如果人工报告测试失败,请修复并重新验证(必要时返回步骤 6 修复编译问题)。
步骤 7c:编写文档
AI 验证和人工验证均通过后:
- 在
.ludeo/tdd/integration-tdd.md中编写或更新本阶段的文档部分 - 记录已实现的内容、做出的关键决策、使用的钩子点,以及与初始计划的任何偏差
- 这是记录,不是审核门槛——保持简洁、客观
步骤 8:发起审核
仅在人工提出要求时,且编译修复已通过后,根据已加载的 vcs/<type>.md 运行 open_review:
- git → 创建 GitHub PR。p4 → 搁置工作变更列表并创建 Swarm 审核(或移交 CL)。
- 根据审核反馈进行迭代
- 将修正内容记录为经验教训
步骤 9:阶段结束后核对
审核已合并/提交(或人工确认阶段已完成)后:
- 将实现修正记录为经验教训
- 更新
integration.json:- 将当前阶段状态设为
completed,并填写completedAt日期 - 将
currentPhase推进到下一阶段 - 将下一阶段状态设为
in_progress
- 将当前阶段状态设为
- 按照进度报告的要求汇报进展。
状态文件架构
该技能会在目标游戏仓库中创建 .ludeo/integration.json。文件记录游戏身份、currentPhase 和各阶段状态(步骤 1 会读取这些信息以便恢复进度)、存档系统分类及其依据、整理后的切片定义、packagingTarget、VCS 配置、SDK 设置,以及逐步积累的 decisions / findings。
完整架构及逐字段说明:references/state-file-schema.md——创建文件(阶段 1 步骤 8)或添加新的顶层字段前,请先阅读。更新时,请保留你不认识的字段——各阶段会逐步积累基础模板之外的字段(例如 intake、pauseMechanism、skillImprovementNotes);切勿根据模板重写文件。
实现后文档记录
每个阶段的代码编译通过后(步骤 7),在 .ludeo/tdd/integration-tdd.md 中撰写一个文档部分:
## Phase N: [Phase Name]
### What was implemented
- [List of classes, files, hook points added]
### Key decisions
- [Decision]: [Rationale] (e.g., "Used OnMatchStateChanged instead of OnMatchStarted because it fires after state replication")
### Hook points used
| Game Hook | SDK Call | File:Line |
|-----------|---------|-----------|
| ... | ... | ... |
### Deviations from plan
- [What changed during implementation vs. initial analysis]
这是一份记录,不是评审关卡。请保持简洁、客观。
评审周期
TDD 获批且代码实现完成后(通过 open_review——参见步骤 8 和 references/vcs/<type>.md):
- 提交工作以供评审——git:PR;p4:搁置的变更列表 + Swarm 评审。
- 人工评审并提供反馈。
- 技能根据反馈迭代代码。
- 合并 / 提交后,将实现修正记录为经验教训。
- 更新 TDD,记录实际情况与计划的差异——说明实现过程中相较于设计发生了哪些变化。
学习记录
学习记录只追加。 新文件应添加到 learnings/{category}/。未经明确的人工批准,绝不会删除或覆盖现有学习记录文件。learnings/ 目录结构(architecture/、save-systems/、common-mistakes/、engine-quirks/)必须已存在——如果不存在,只创建缺失的子目录,绝不重新创建整个目录树。请参阅 破坏性操作防护。
发现问题时立即记录学习内容,不要等到阶段结束。 发生以下任一情况时,必须在继续之前写下学习记录(或技能改进说明)——不要等到阶段末尾才批量记录,否则细节和上下文都会丢失:
- 修复问题花了不止一次尝试,或根本原因与你最初的猜测不同;
- SDK、引擎或环境的行为与技能或其文档的描述不同;
- 人类纠正了你,或你偏离了参考集成;
- 你发现了不明显的前置条件、顺序要求或精确的 API 签名。
立即记录成本很低,而且上下文仍然鲜活;延后记录会丢失让学习内容可复用的具体细节。请按照 references/learning-sanitization.md 进行清理。如果不确定某项内容是可复用的学习经验还是一次性的情况,应将其视为学习经验并简要记录。
当技能收到纠正意见时(来自 TDD 审查或 PR 反馈):
-
按主题分类:
architecture— 插件结构、子系统设计、组件模式save-systems— 存档系统分类、序列化、SaveWorld 决策common-mistakes— 技能之前犯过的错误engine-quirks— UE 特有的注意事项(UHT、复制、GAS)
-
按级别分类:
universal— 适用于所有游戏。可直接用于未来的集成。generalizable— 广泛适用,但实现方式各异。请附上一个供未来集成时向人类提出的问题。game-specific— 仅与此游戏相关。作为示例保存,不用于其他游戏。
-
使用 frontmatter 写入
learnings/{category}/:--- category: architecture tier: universal sourceGame: ActionGame # abstract codename only — see allowlist below phase: 1 question: null sanitized: true # attest you ran the sanitization checklist ---对于
generalizable级别,question应包含技能在未来集成时应提出的问题(例如:“这款游戏的存档系统是否支持任意存档点,还是只支持检查点?”)。然后将其登记到索引中: 将该学习记录对应的行追加到
learnings/INDEX.md(path | tier | s<phase> | question-or-title,格式与现有条目一致),或者在条件允许时运行node scripts/generate-learnings-index.mjs。步骤 3 会先加载索引——未列入索引的学习记录对后续阶段不可见。 -
保存前必须进行清理。 未来的集成会读取相关学习记录,供其他客户端使用;任何遗留的客户端特定信息都会将一个客户端的代码泄露给其他所有客户端。只记录可迁移的模式,绝不记录客户端的内容:
sourceGame:必须使用允许列表中的抽象代号(config/learning-policy.json),客户端标识符应改为中性的、基于角色的名称,Ludeo SDK 和 UE 原生标识符则保持原样。测试标准: 读者能否说出客户端名称,或复制粘贴属于该客户端的内容?如果能,就说明清理不到位。这适用于每个已提交的文件,而不仅是learnings/——绝不要提交包含客户端标题、类名或地图名,或仓库路径的规划文档或笔记。完整规则、检查清单、命名约定和翻译键:
references/learning-sanitization.md——编写任何学习记录前请先阅读。scripts/validate-skill.mjs会检查结构要求。 -
未来的集成会按阶段和类别筛选相关学习记录,并在生成 TDD 前加载这些记录。
MCP 配置
此技能在 config/mcp_config.template.json 中提供 MCP 服务定义,并在会话开始时检查这些服务。**这些服务运行在集成人员的机器上——它们属于已安装的技能,而不是此仓库的工具。**将相关条目复制到 Agent 的 MCP 配置中(Claude Code:项目根目录下的 .mcp.json,或使用 claude mcp add),填入已脱敏的凭据,然后启动新会话以连接这些服务。
| 服务 | 托管端点 | 用途 | 后备方案 |
|---|---|---|---|
sdk-docs | https://ludeo-mcps-sdk-docs.ludeo.com/mcp(HTTP,X-User-Name 标头) | 搜索 Ludeo SDK 文档——API 参考、方法签名、参数结构体、回调链 | 随附的 references/sdk-reference/ 文件(仅含概念) |
ludeo-context | https://mcp-ludeo-context-internal.ludeo.com/mcp(HTTP,Bearer 令牌) | 公司知识、QA 工作流、仓库上下文、集成模板 | 无需此服务也可继续;分析质量可能会降低 |
ludeo-mcp | https://mcp.ludeo.com/mcp(HTTP,OAuth 登录) | Studio Labs 平台操作——否则 Agent 会交由人工处理,包括环境、用于将本地运行路由到某个环境的 Beta Version Name,以及邀请 | 请人工在 Studio Labs 中完成此步骤 |
各 MCP 服务的使用时机:
sdk-docs:任何阶段——只要技能需要查阅或搜索 SDK 文档,就使用此服务。这是文档搜索服务;优先使用它,而不是猜测或查阅随附的概念文件。ludeo-context:阶段 2(映射分析)、阶段 5–6(从 QA 事件列表中发现跟踪/恢复和操作)。ludeo-mcp:阶段 1(环境查找)和阶段 3 §3.16(用于将本地运行路由到某个环境的 Beta Version Name;云构建由builds assign绑定)。交互点、调用频率和读写策略:references/ludeo-studio-mcp.md——读取免费,写入需确认。
如果未检测到某个服务,请先根据 config/mcp_config.template.json 配置它(见步骤 4),再使用其后备方案,并告知人工你正在使用哪种后备方案。
参考文件结构
每个阶段的参考文件(references/phase-*.md)都遵循一致的章节结构:
分析阶段(阶段 2)分为 7 个章节:
- 目标——此阶段的产出(具体交付物)
- 输入——开始前技能所需的信息,以及正式的输入约定(前序阶段的输出、游戏信息)
- 分析清单——在代码库中需要查找的内容以及可用的方法(grep 模式、类层次结构、委托声明)。对于 MVP 阶段(3–5),范围限定为精选内容。
- 需要向人工询问的问题——仅涉及无法从代码推断的决策
- 应用的模式——来自先前集成的通用模式(Lyra、FPS Kit)
- 文档模板——实现后需要记录的内容
- 常见错误——先前集成在此阶段出现的问题
产出代码的阶段(阶段 3–9)会增加第 8 个章节:
- 实现指南——插件脚手架、类骨架、编译修复循环、配置设置。阶段 3 使用来自
references/templates/的模板驱动方法。 - 常见错误——(从第 7 节移至第 8 节)
参考文件按需加载——每次仅将当前阶段的文件读入上下文。
参考示例与经验
references/reference-sample-catalog.md— 已知可靠集成参考示例的权威索引(FPSGameStarterKit、Lyra、VoyagerV2 等),包含匹配条件及其对应的分类。在从头推导分类之前,先查阅此文件——匹配到示例比基于 grep 的推断更有力。此类已完成集成中的模式和决策依据也记录在learnings/中(按sourceGame筛选)。references/game-patterns/— 按类型和结构划分的操作指南(动作目录、追踪检查清单、Unreal grep 惯用写法、开放世界会话规范、回合制节奏)。在阶段 02/05 按类型加载;通过其INDEX.md进行分类。learnings/— 记录以往集成中的分类纠正。按主题组织(architecture/、save-systems/、common-mistakes/、engine-quirks/)。每个文件都包含 frontmatter,可按层级、阶段和源游戏筛选。
以上内容会根据当前阶段的需求按需加载和筛选。
存档系统分类
游戏会在阶段 2 被分为以下三组之一:
| 组别 | 说明 | 集成策略 |
|---|---|---|
| 1 — 完整存档 | 游戏已有存档系统(例如 SaveGame 类) | 利用现有序列化机制;可考虑使用 SaveWorld |
| 2 — 仅检查点 | 游戏只在固定节点存档 | 扩展检查点系统,以支持任意存档点 |
| 3 — 无存档 | 除会话状态外,没有现有的持久化机制 | 从头构建状态捕获功能(AI 在此最能发挥作用) |
此分类将影响阶段 5(精选状态追踪 + Player Flow 恢复方案)以及阶段 8–9(完整游戏覆盖和完善)。
何时询问,何时推断
通过代码分析进行推断:
- 事件系统(搜索
DECLARE_DYNAMIC_MULTICAST_DELEGATE、UGameplayMessageSubsystem、自定义事件总线) - 阶段/状态机(状态枚举、阶段管理器、游戏模式状态)
- 存档系统(
SaveGame类、序列化调用、检查点逻辑) - 实体类型(Pawn 类、角色类、AI 控制器)
询问用户:
- 存在多种有效方案(写入频率、去重策略、SaveWorld 与手动实现之间的选择)
- 需要游戏领域特定知识(“什么算是重要操作?”)
- 代码分析结果不明确(“这个委托是合适的挂接点吗?”)
- 性能权衡需要判断(状态大小与更新频率)
- 代码中看不出顺序/时序依赖(延迟处理的生命值、跳过阶段)
- 只要有任何事情不够明确,无法做出有把握的决定,就询问用户。
- 不确定时就说不知道。询问总比猜错好。
绝不能仅凭编译/打包成功就声称“已验证”或“阶段已完成”。 编译只能证明代码可以构建,不能证明代码能在运行时正常工作。务必提供运行时测试清单(步骤 7b),并等待用户确认。这是最常见的流程失误——Agent 会因为无法亲自运行游戏,而为跳过运行时验证找理由。
调试与诊断门槛
当用户报告运行时故障或提出诊断问题时,交付内容必须按以下顺序在聊天中给出:调查结果 → 根本原因 → 拟议更改。**只有在用户确认诊断后,才能开始实施。**仍在诊断时,不要开始编辑代码。
确认根本原因之前,不得提出推测性的缓解措施。重试循环、超时、强制开始计时器以及其他兜底措施,在用户确认经过验证的根本原因之前一律禁止。这些措施会扭曲 Ludeo 的保真度,而且往往会掩盖真正的错误(生命周期损坏),而不是修复它。兜底措施是针对已知且已找到根本原因的问题的修复手段,绝不能用来探查问题。
**提出任何修复方案前,先搜索经验总结并引用匹配项。知识库中已经收录了常见故障类型。提出修复方案前,先在 learnings/ 中搜索相关症状,并说明匹配了哪条经验总结(或说明没有匹配项)。尤其是遇到“第一个房间或会话正常运行后,后续房间或会话中缺少 SDK 信号/通知”**的情况(例如,房间 N>1 时 OnRoomReady 始终未触发):原因几乎总是你的生命周期有问题——先审查房间 N-1 的清理流程。请参阅 learnings/common-mistakes/dont-bypass-sdk-when-your-lifecycle-is-broken.md、learnings/architecture/detached-teardown-for-game-initiated-travel.md 和 learnings/architecture/onroomready-is-the-viewer-connected-gate.md(其中包含本地运行的诊断顺序)。不要臆造结构性理论(“本地回放没有观众,因此 OnRoomReady 不会触发”)——OnRoomReady 始终会通过叠加层在本地触发。