关于 scenario-unity-pipeline-automation
scenario-unity-pipeline-automation 面向 Unity 工具和构建工程师,帮助建立可重复的内容流水线。内容涵盖确定性导入、序列化编辑、Addressables 打包、测试门禁和从干净检出运行 CI,并通过计数与重跑检查验证稳定性。
主要功能
- 01确定性资源导入规则
- 02序列化资源与预制件编辑
- 03Addressables 分组与内容构建
- 04构建前测试与发布门禁
- 05玩家构建冒烟测试
- 06CI 流水线生成
适用场景
- 01自动处理批量导入的 FBX 资源
- 02按加载条件构建内容包
- 03通过内容测试把关玩家版本发布
- 04从干净的 CI 检出运行构建
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ scenario-labs/ skills --skill scenario-unity-pipeline-automation安装后在 Claude Code 中输入/scenario-unity-pipeline-automation确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/critique.mdexpert-notes.mdgui-paths.mdprocedures.mdsources.mdscripts/ut_pipeline.pyscripts/AgentKit/Pipeline/AddressablesJobs.csArtDropJobs.csEditorEditJobs.csPipelineBuild.csPipelineChecks.csPipelineRules.csPropImportPostprocessor.csscripts/AgentKit/Pipeline/Tests/PipelineContentTests.csscripts/AgentKit/PipelineCli/AgentKit.PipelineCli.asmdefPipelineCliCommands.csscripts/Runtime/AgentAddressablesSmoke.csscripts/templates/PipelineAsmdef/Editor/Game.Pipeline.Editor.asmdefTextureRuleAudit.csscripts/templates/PipelineAsmdef/Tests/Game.Pipeline.Tests.asmdefTextureRuleTests.cs详细介绍
Unity 流水线自动化(工具与构建工程师)
这里的专家级水平意味着:流水线在每台机器、每次运行中都能产出相同结果;导入时应用规则,通过序列化进行编辑,按加载时机打包内容,用测试把关构建,并由 CI 从干净的检出版本运行构建。原则是:不重复手动操作,不凭空信任任何结果,必须有数量统计、测试或帧作为依据;再次运行时不应产生任何变化。如果此处提到的同级技能不在你可用的技能中,请让用户安装它(npx skills add scenario-labs/skills --skill <name>);在无人值守的情况下,根据工具架构继续操作并指出这一缺口。
必备背景: scenario-unity-expert(通道、作业协议、审查循环、6.3 陷阱)。
导入其工具包;此技能新增 scripts/ut_pipeline.py 和
scripts/AgentKit/Pipeline/。
状态(2026-09-24,盲测评分重构后): 所有流程都已在这台 Mac 上使用 Unity 6000.3.21f1 针对一批 200 个 FBX 的 Blender 导出文件运行:tests/code/unity-pipeline-automation/(结果位于
archive/tests/unity-pipeline-automation/live_results.jsonl)。
立场(专家观点差异)
- 导入规则是在导入时运行的代码,必须保证确定性并加以验证。 在
OnPreprocess*中设置选项,每次代码变更都递增GetVersion(),先声明配置再读取 (context.DependsOnSourceAsset),不使用时钟、不依赖字典顺序、不在回调中写入资源 (6.3 Manual;Javier Abud Chavez,S2P9n5U9xVw [00:04:35]、[00:19:29])。验证方式:在信任共享缓存或 CI 前运行-consistencyCheck(Manual)。观察结果:23.5 秒检查了 12,184 个资源;随机像素探测纹理被标记,受管理的 593 个文件中有 0 个被标记。递增版本号或新增后处理器,会重新导入该导入器类型的所有资源,包括程序包(1,513 个纹理)。 - 只有通过序列化修改了确切的对象,编辑才算生效。 在变更前,对被修改的组件记录 Undo(Freya Holmér,pZ45O2hg_30 [03:01:01])。观察结果:执行
Undo.RecordObject(go)后移动对象,操作无法撤销;执行RecordObject(go.transform)则可以。直接写入预制件实例会在下次预制件更新时还原;ScriptableObject 若未调用SetDirty,则不会保存。 - 每个阶段只进行一次 AssetDatabase 批处理,并测量耗时。 使用
try/finally包裹StartAssetEditing/StopAssetEditing(Abud Chavez [00:30:21]),并在其中调用SaveAndReimport/ImportAsset。使用 AssetDatabase 计数器统计,不要依赖日志(Abud Chavez [00:26:44])。观察结果:对 195 个 FBX 执行两轮重映射,逐个处理耗时 19.0 秒,批量处理耗时 5.1 秒。 - 按加载条件而非文件夹打包 Addressables,并保持顺序稳定。 在完全相同条件下所需的资源应放在同一组;多个组共用的依赖项应显式放置(Olle Axelsson,Valheim,Fzu2Das_1FU [00:23:08])。未分配的共享依赖项会被复制到每个 Bundle 中 [00:18:44];观察发现,其中包括 URP 的
Lit.shader。按序号顺序分配(6.3 Manual,Addressables 确定性):2.9.1 保存时会按 GUID 对组和条目排序,但标签表会保留插入顺序。 - 释放不等于卸载,引用也会触发加载。 当 Bundle 的引用计数降至零时,内存才会释放(Addressables 2.9 手册);引用 Addressable 内容的构建场景会在加载场景时加载这些内容,并再次从 Bundle 加载(Code Monkey,C6i_JiRoIfk [00:03:32];Axelsson [00:24:49])。为其设置门控;在播放器中测量卸载情况。
- 在启动时固定平台,并确保每个阶段的平台一致,同时发布构建时使用的内容。 在批处理作业中切换目标无效(Manual;Thom Hopper,BlVsi2cSJ88 [00:27:18]);构建目标是导入依赖项(Abud Chavez [00:15:49])。观察结果:一个阶段在 Android 上重新导入了 1,717 个资源,耗时 52 秒;切换回去后复用了缓存产物(60 次导入)。Addressables 的默认设置会在每次播放器构建中重新构建所有内容。
- 测试是发布门槛。 将内容规则编写为参数化的 Edit Mode 测试,每个资源对应一个用例(Warnecke 和 Fine,wTiF2D0_vKA [00:24:28]),并在预构建回调中同步运行,记录通过信息
[00:31:43]。除非使用
LogAssert.Expect预期了日志,否则任何错误日志都会导致测试失败(Manual);观察发现,这也包括测试中重新导入所记录的导入错误。使用-runTests时绝不要加-quit。 - 发布构建应来自干净的代码树,不启用调试定义,并保留溯源信息(文档摘要检查清单;Hopper,配置定义)。优先使用范围明确的命名工具,而非通用执行(git-amend,VPjo-M6mPkE [00:03:54];Unity,DgNrgZeJOxQ [00:07:41])。
首先确定
- 交付内容约定: DCC 和导出设置、每个类别的文件夹、后缀、单位。默认值:Blender
“FBX All” + “Apply Transform”,
_BaseColor/_Normal,并用manifest.csv记录额外标签。 - 加载条件: 按集合(关卡、生物群系)加载,还是逐个加载?默认值:标签,
key_by="label";流式加载使用key_by="root"。 - 目标和预算: 平台(每次流水线运行使用一个
-buildTarget)、每个平台的纹理上限、顶点预算、每个标签的资源包预算。默认值:桌面端 1024 px,移动端 512 px,5,000 个顶点。 - 内容更新: 发布后是否有远程内容?按平台、按发布版本归档
addressables_content_state.bin。 - 渠道和 CI: 用户是否在该项目中打开了编辑器(
ut_live.channel(P))?是否有 Git 仓库?是否有 Accelerator?许可证:Personal(仅需登录 Hub)或付费席位。
工作流
- 预检。
ut_env.preflight(P);ut_pipeline.install(P)。编辑器已打开:通过ut_live.call或[CliCommand]工具执行相同任务。团队测试必须调用的流水线代码:项目自己的 Editor asmdef 和一个测试 asmdef(install_asmdef_template)。GATE:Echo正常,编译错误为 0(一个错误就会中止所有批处理任务)。 - 离线扫描交付内容。
up.scan_drop(drop),规则相同,使用 JSON。GATE:每个拒收项都有原因;重复项的每个副本都拒收。 - 导入。
up.import_drop(P, drop, target=T):将更改的文件导入<root>/<Category>/<Name>/,单次批处理,并进行审计。GATE:已接受数量 = 找到数量 - 拒收数量;审计错误均有说明;后处理器更改后,up.consistency_check(P, target=T)不会在Assets/下标记任何内容。 - 材质和预制件。
up.build_prefabs(P, target=T):每个道具使用 URP Lit 材质,根据ShaderGUI.ValidateMaterial设置关键字,在批处理中通过SaveAndReimport重新映射 FBX,在预览场景中构建 Prefab Variants,仅在值发生更改时保存。GATE:预制件数量 = 已接受数量 - 尺寸错误数;重新运行后重写文件数为 0(git status干净)。 - 查看效果。 依次运行
EditorEditJobs.BuildLineup、启用graphics=True的AgentCapture.CaptureViews、ut_review.review_capture,然后打开图集。GATE:没有洋红色、黑色或空白标记;道具直立、落地且比例正确。 - Addressables 组。
up.assign_addressables(P, "condition", target=T)。GATE:implicit_duplicates == 0;up.hard_references(P)正常。 - 构建内容。
up.build_content(P, T):构建器索引>= 0,执行ClearCachedData+BuildCache.PurgeCache(false),设置DoNotBuildWithPlayer,回读布局,并归档状态。GATE:重复资源数为 0,每个标签的字节数均在预算内。 - 测试。
ut_run.run_tests(P, "EditMode", categories="PipelinePreBuild", extra_args=["-buildTarget", up.cli_target(T)])。 GATE:失败数为 0,总数等于预期资源数。 - 构建 Player。 从已提交的模板复制配置文件(使用
template调用PipelineBuild.CreateBuildProfile),然后运行ut_run.build(P, T, profile=...),或直接使用-activeBuildProfile ... -executeMethod AgentKit.Pipeline.PipelineBuild.BuildFromCommandLine。 发布:使用-agentRelease(门禁会拒绝调试定义),确保工作树干净,并运行up.release_ready(repo, app)。 GATE:AGENT_GATE正常,hard_references为 0,BuildReport 状态为Succeeded。 - 冒烟测试 Player。
up.player_smoke(app, label)。GATE:已加载资源数量等于清单数量;释放后资源包已卸载。 - CI。
up.write_ci(repo):生成ci/pipeline.sh(每个阶段使用一个进程;每个阶段使用相同的-buildTarget;设置ACCELERATOR=、CONSISTENCY=1、RELEASE=1)和 GitHub Actions 文件。GATE:从不含Library/的检出目录运行并通过;许可证通过if: always()归还;启用 Accelerator 时,日志中的cache server=计数大于 0。
数字
| 数值 | 对比对象 | 来源 |
|---|---|---|
| 5.6 到 6.7 s | 一次性复制并导入 593 个文件 | 实测 |
| 19.0 s vs 5.1 s | 对 195 个 FBX 执行两轮重映射(SaveAndReimport),逐个执行 vs 一次性批量执行 | 实测 |
| 11 到 12 s | 197 个材质、197 个 FBX 重映射、196 个 Prefab Variant,在编辑器中的耗时 | 实测 |
| 1,717 次导入,52 s / 60 次导入 | 首次在另一个平台启动 / 切换回来(已缓存的构件) | 实测 |
| 1,513 张纹理,17 s | 一个不执行任何操作的纹理后处理器的 GetVersion() 递增后重新导入 | 实测 |
| 检查 12,184 项,23.5 s | 此项目的 -consistencyCheck(跳过 7,390 项;标记了 2 个 URP 着色器:基线包) | 实测 |
| 0 个文件 | 第二次完整运行(导入、预制件、分组)所更改的文件 | 实测 |
| 791 项测试,10 到 16 s | 针对 196 个预制件、396 张纹理、197 个模型的内容测试 | 实测 |
| 13.5 / 12.9 / 4.8 MB | 最差的标签加载量,分类 / 隔离 / 条件布局(3 个生物群系) | 实测 |
| 5 | 分类布局中的重复资源(2 张纹理、Lit.shader、2 个回退资源) | 实测 |
| 0 到 63 ms | 最后一次 Release 后仍加载的 AssetBundle(7 次玩家运行) | 实测 |
| 60 到 158 s / 5 到 23 s | 首次 macOS Mono 玩家构建 / 增量重建(共享机器);玩家包 127.4 MB | 实测 |
| 0.4 到 1.2 s vs 10 到 17 s | 同一任务通过常驻编辑器的桥接执行 vs 启动编辑器的批处理任务 | 实测 |
| 4 GB | 为跨平台兼容性设定的每个 AssetBundle 上限 | Addressables 2.9 手册 |
| 30,000 个顶点 | FBX 预算警告示例 | Unity 教程,qZ5NmyoxKRk [00:03:55] |
| 38%,约 110 MB | Valheim 通过流式加载减少的内存,随后通过减少已加载的 AssetBundle 进一步降低 | Axelsson [00:03:02], [00:30:41] |
| 179 s / 486 s | 从没有 Library/ 的检出目录生成 ci/pipeline.sh(v0.2,空闲机器 / v0.1,有 6 到 8 个其他编辑器运行) | 实测 |
| 0 / 8 / 6 | unity test 退出码:通过 / 测试失败(绝不重试)/ 无结论(重试) | unity-cli 技能 |
质量门禁
- **可衡量:**信封
ok,无编译错误,每个阶段的active_target均相同;ImportDrop 计数;Assets/下的一致性检查通过;预制件数量;重新运行:复制数为 0,git status无更改;implicit_duplicates为 0,且duplicated_assets为 0;按标签统计 KB;无硬引用 Addressable 内容的构建场景;NUnit 失败数为 0,且总数符合预期;AGENT_GATE为 ok;BuildReport 为Succeeded;玩家冒烟测试计数;发布:工作树干净,来源记录source.dirty为 false,无禁止的定义;CI 脚本从干净检出运行,退出码为 0。 - **视觉:**已打开排列图:没有洋红色;法线贴图着色正常;道具直立;枢轴位于地面;与 1.8 m 胶囊体相比,尺寸合理。
常见错误
| 错误 | 表现 | 修复 |
|---|---|---|
在 OnPostprocessTexture 中设置导入器选项;代码已更改,但未提升 GetVersion() 版本 | 使用旧设置;不同机器结果不一致 | 使用 OnPreprocess*;提升版本;使用 -consistencyCheck |
| 在规则 JSON 中添加非导入器键 | 所有受管控资源都会重新导入 | 使用单独的文件(pipeline_checks.json) |
移动对象前调用 Undo.RecordObject(gameObject) | 移动操作无法撤销 | 记录 Transform |
| 直接写入预制件实例或 ScriptableObject | 下次更新预制件时被还原/文件未更改 | 使用 RecordPrefabInstancePropertyModifications/SetDirty |
未使用 finally 的 StartAssetEditing;批处理之外对每个 FBX 调用 SaveAndReimport | 数据库冻结;重新映射速度慢 4 倍 | 使用 try/finally;在批处理中重新导入 |
各阶段使用的 -buildTarget 不一致 | 每个阶段都会重新导入纹理和着色器 | 所有阶段(包括测试)使用相同目标 |
| 每个文件夹单独建组,却共享纹理 | 每个包中都包含相同的纹理和着色器 | 条件打包;检查构建布局 |
| 按文件顺序或 HashSet 顺序添加标签 | 不同机器上的设置文件内容不一致 | 使用序数排序 |
| 构建场景引用了一个 Addressable 预制件 | 加载两次,绕过包 | 在门禁中使用 HardReferences |
| 构建内容后又执行默认玩家构建 | 内容被重新构建,归档状态过时 | 使用 DoNotBuildWithPlayer + 门禁 |
在批处理作业中调用 SetActiveBuildProfile;使用来自内部 API 的配置文件 | 目标平台或定义过时;升级后失效 | 使用 -activeBuildProfile;复制已提交的模板 |
| 测试重新导入的资源,其导入器会记录错误 | 出现 "Unhandled log message",测试失败 | 使用 LogAssert.Expect |
| 测试位于 test asmdef 中,却调用 Assembly-CSharp-Editor 中的代码 | 出现 CS0103,每个批处理作业都中止 | 将管线代码放入单独的 Editor asmdef |
使用 Accelerator 时调用 -quit,但未设置等待标记;服务器无法访问 | 上传丢失;作业静默通过 | 使用 -cacheServerWaitForUploadCompletion;检查 cache server= |
| 从有未提交更改的工作树发布 | 来源信息为 dirty: true,CLI 仍会构建 | 保持工作树干净,设置 RELEASE=1,将 Addressables 的 link.xml 加入 gitignore |
| Blender 默认 FBX 导出 | 根节点旋转 90 度,缩放比例为 100 | 选择 FBX All + Apply Transform(scenario-blender-export) |
| 按顺序解决重复名称 | 错误资源会悄然胜出 | 拒绝所有副本并询问 |
| 在作业中创建 Addressables 设置 | 下一次运行时会重写设置文件 | 在 GetSettings(true) 后设置这两种提供程序类型 |
使用 -quit 和 -runTests;--output-path 为相对路径 | 没有 XML;构建输出位于项目之外 | 省略 -quit;使用绝对路径 |
交接
- 接收: 来自 scenario-blender-export、scenario-maya-expert、scenario-3d、scenario-textures 的 FBX、纹理及导出设置;来自 scenario-unity-architecture 的代码布局和 asmdefs;来自 scenario-unity-world-building 的道具加载分组信息。
- 交付: 向 scenario-unity-performance 提供构建报告、资源包大小和各标签的加载情况;向 scenario-unity-mobile 提供纹理格式(此技能只设置尺寸上限)和签名构建;向 scenario-unity-web 提供 Web 构建(WebGL 上不使用
WaitForCompletion);向 scenario-unity-rendering-lighting 提供光照贴图 UV 需求;向负责人提供规则 JSON、道具清单、包络、NUnit 总数、布局 JSON、BuildReport、来源信息和联系表。
Unity 6.3 说明
- Addressables 2.9.1 是此编辑器的默认版本(文件夹键和
await handle属于 4.0);其后处理器会将任何导入的组资源采用到默认设置中。6.6 中,内容目录将取代 AssetBundle 构建。 IPreprocessBuildWithContext也会在 AssetBundle 构建时触发:使用BuildPipeline.isBuildingPlayer进行筛选。- 6.5 之前没有公开的配置文件创建 API;AssetDatabase 计数器可通过
UnityEditor.Experimental.AssetDatabaseExperimental.counters公开访问。 - Unity CLI 处于 Beta 阶段;
unity build会在 macOS 上将来源清单写入.app内。个人许可证只能通过 Hub 登录激活。
参考资料
references/procedures.md:以可复制调用的形式介绍流水线,每项都附带实时测试和结果。references/expert-notes.md:专家提出的原则和判断,附有来源和时间戳。references/critique.md:用于评判流水线、布局、构建和发布的评分标准。references/gui-paths.md:执行相同任务所用的窗口和菜单。references/sources.md:所有来源及其凭据、URL、时间戳和修订历史。scripts/ut_pipeline.py、scripts/AgentKit/Pipeline/*.cs(作业、后处理器、检查、门禁、内容测试)、scripts/AgentKit/PipelineCli/、scripts/Runtime/、scripts/templates/PipelineAsmdef/:代码。