mcpField
S
scenario-unity-pipeline-automation

scenario-unity-pipeline-automation

github.com/scenario-labs開発1.2k251 回インストール1 日前に更新
リポジトリ

scenario-unity-pipeline-automation について

scenario-unity-pipeline-automationは、再現可能なコンテンツパイプラインを構築するUnityのツール・ビルドエンジニア向けスキルです。決定的なインポート、シリアライズを介した編集、Addressablesのパッケージ化、テストを通したビルド、クリーンなチェックアウトからのCIを扱い、件数と再実行時の安定性を確認します。

主な機能

  1. 01決定的なアセットインポート規則
  2. 02アセットとプレハブのシリアライズ編集
  3. 03Addressablesのグループ化とコンテンツビルド
  4. 04ビルド前テストとリリースゲート
  5. 05プレイヤーのスモークテスト
  6. 06CIパイプラインの生成

活用シーン

  1. 01大量のFBXアセットのインポート自動化
  2. 02ロード条件に基づくコンテンツバンドルの構築
  3. 03コンテンツテストによるプレイヤーリリースの判定
  4. 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.md
expert-notes.md
gui-paths.md
procedures.md
sources.md
scripts/
ut_pipeline.py
scripts/AgentKit/Pipeline/
AddressablesJobs.cs
ArtDropJobs.cs
EditorEditJobs.cs
PipelineBuild.cs
PipelineChecks.cs
PipelineRules.cs
PropImportPostprocessor.cs
scripts/AgentKit/Pipeline/Tests/
PipelineContentTests.cs
scripts/AgentKit/PipelineCli/
AgentKit.PipelineCli.asmdef
PipelineCliCommands.cs
scripts/Runtime/
AgentAddressablesSmoke.cs
scripts/templates/PipelineAsmdef/Editor/
Game.Pipeline.Editor.asmdef
TextureRuleAudit.cs
scripts/templates/PipelineAsmdef/Tests/
Game.Pipeline.Tests.asmdef
TextureRuleTests.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)。

スタンス(専門家との差分)

  1. インポートルールはインポート時に実行されるコードであり、決定論的であることを証明します。 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個)。
  2. 変更として認められるのは、正確なオブジェクトに対してシリアライズを経由した場合だけです。 変更前に、変更するコンポーネントに対して Undo を記録します(Freya Holmér、pZ45O2hg_30 [03:01:01])。確認結果:Undo.RecordObject(go) の後に移動しても元に戻せませんが、RecordObject(go.transform) なら元に戻せます。Prefab インスタンスに直接書き込むと、次の Prefab 更新時に変更が取り消されます。ScriptableObject は SetDirty を呼ばないと保存されません。
  3. 各ステージで AssetDatabase のバッチ処理を1回実行し、計測します。 try/finally 内で StartAssetEditing / StopAssetEditing を使用します(Abud Chavez [00:30:21])。SaveAndReimport / ImportAsset もその中で実行します。ログではなく AssetDatabase のカウンターで数えます(Abud Chavez [00:26:44])。確認結果:FBX 195個に対する2回のリマップ処理は、1つずつ行うと19.0秒、バッチ処理では5.1秒でした。
  4. Addressables はフォルダー単位ではなく、読み込み条件ごとに安定した順序でパックします。 まったく同じ条件下で必要となるアセットは同じグループにまとめ、複数のグループで使用される依存関係は明示的に配置します(Olle Axelsson、Valheim、Fzu2Das_1FU [00:23:08])。割り当てられていない共有依存関係は各バンドルにコピーされます [00:18:44]。確認したところ、URP の Lit.shader も含まれていました。序数順で割り当てます(6.3 Manual、Addressables determinism):2.9.1 は保存時にグループとエントリーを GUID 順に並べ替えますが、ラベルテーブルは挿入順を維持します。
  5. リリースしてもアンロードされるわけではなく、参照は読み込みです。 バンドルの参照カウントがゼロになると、メモリが解放されます(Addressables 2.9 manual)。Addressable コンテンツを参照するビルドシーンは、シーンと一緒に読み込まれ、さらにバンドルからも読み込まれます(Code Monkey、C6i_JiRoIfk [00:03:32];Axelsson [00:24:49])。その動作をゲートし、プレイヤー内でアンロードを計測します。
  6. 起動時にプラットフォームを固定し、すべてのステージで同じ設定を維持して、ビルドしたコンテンツを出荷します。 バッチジョブ内でターゲットを切り替えても何も起こりません(Manual;Thom Hopper、BlVsi2cSJ88 [00:27:18])。ビルドターゲットはインポートの依存関係です(Abud Chavez [00:15:49])。確認結果:Android で実行した1つのステージでは、1,717個のアセットが52秒かけて再インポートされました。元に戻す際にはキャッシュされた成果物が再利用されました(インポート60個)。Addressables のデフォルト設定では、すべてのプレイヤービルド内で全コンテンツが再ビルドされます。
  7. テストをゲートにします。 コンテンツルールは、アセットごとに1ケースを設けたパラメトリックな Edit Mode テストとして実装し(Warnecke and Fine、wTiF2D0_vKA [00:24:28])、合格をログに記録するプリビルドコールバック内で同期実行します [00:31:43]。ログに記録されたエラーは、LogAssert.Expect で事前に指定されていない限りテストを失敗させます(Manual)。確認したところ、テスト内の再インポートで記録されたインポートエラーも該当しました。-runTests と一緒に -quit を指定してはいけません。
  8. リリースビルドは、デバッグ用の定義を使わず、由来を維持したクリーンなツリーから作成します(docs digest checklist;Hopper、profile defines)。汎用的な実行より、対象を絞った名前付きツールを使います(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 を 1 つ指定)、プラットフォームごとのテクスチャ上限、頂点予算、ラベルごとのバンドル予算。デフォルト:デスクトップは 1024 px、モバイルは 512、頂点数は 5,000。
  • コンテンツの更新: リリース後にリモートコンテンツを更新するか。リリースごと、プラットフォームごとに addressables_content_state.bin をアーカイブします。
  • チャネルと CI: ユーザーのエディターでプロジェクトが開かれているか(ut_live.channel(P))。Git リポジトリはあるか。Accelerator はあるか。ライセンス:Personal(Hub へのサインインのみ)または有料シート。

ワークフロー

  1. 事前チェック。 ut_env.preflight(P);ut_pipeline.install(P)。エディターが開いている場合は、同じジョブを ut_live.call または [CliCommand] ツール経由で実行します。チームのテストから呼び出すパイプラインコードには、専用の Editor asmdef とテスト用 asmdef が必要です(install_asmdef_template)。GATE:Echo が成功し、コンパイルエラーが 0 件であること(1 件でもあると、すべてのバッチジョブが中断します)。
  2. 納品物をオフラインでスキャン。 up.scan_drop(drop)、同じルール JSON を使用します。GATE:却下されたすべてのファイルに理由があること。同一ファイルが重複している場合は、すべてのコピーを却下します。
  3. インポート。 up.import_drop(P, drop, target=T):変更されたファイルを <root>/<Category>/<Name>/ にインポートし、1 回のバッチで処理して監査します。GATE:受け入れ数 = 検出数 - 却下数。監査エラーの説明があること。ポストプロセッサの変更後に up.consistency_check(P, target=T) を実行し、Assets/ 配下に何も検出されないこと。
  4. マテリアルとプレハブ。 up.build_prefabs(P, target=T):プロップごとに URP Lit を使用し、ShaderGUI.ValidateMaterial に従ってキーワードを設定します。バッチ内で SaveAndReimport を使って FBX をリマップし、プレビューシーンで Prefab Variants を作成します。値が変更された場合のみ保存します。GATE:プレハブ数 = 受け入れ数 - サイズエラー数。再実行で書き換えられるファイルが 0 件(git status がクリーン)であること。
  5. 見た目を確認。 EditorEditJobs.BuildLineup の後に AgentCapture.CaptureViews を graphics=True で実行し、ut_review.review_capture を使ってシートを開きます。GATE:マゼンタ、黒、空白のフラグがないこと。プロップが直立し、地面に接し、適切なスケールであること。
  6. Addressables グループ。 up.assign_addressables(P, "condition", target=T)。GATE:implicit_duplicates == 0 であること。up.hard_references(P) が成功すること。
  7. コンテンツをビルド。 up.build_content(P, T):ビルダーインデックスが >= 0、ClearCachedData と BuildCache.PurgeCache(false) を実行し、DoNotBuildWithPlayer を使用します。レイアウトを読み戻し、状態をアーカイブします。GATE:重複アセットが 0 件で、ラベルごとのバイト数が予算内であること。
  8. テスト。 ut_run.run_tests(P, "EditMode", categories="PipelinePreBuild", extra_args=["-buildTarget", up.cli_target(T)])。 GATE:失敗数が 0 件で、合計数が想定アセット数と一致すること。
  9. プレイヤーをビルド。 コミット済みのテンプレートからプロファイルをコピーします(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 であること。
  10. プレイヤーのスモークテスト。 up.player_smoke(app, label)。GATE:読み込まれたアセット数がマニフェストの件数と一致し、リリース後にバンドルがアンロードされること。
  11. CI。 up.write_ci(repo):ci/pipeline.sh(ステージごとに 1 つのプロセスを使用し、各ステージで同じ -buildTarget を指定。ACCELERATOR=、CONSISTENCY=1、RELEASE=1)と GitHub Actions のファイルを生成します。GATE:Library/ のないチェックアウトから実行して成功すること。ライセンスが if: always() で返却されること。Accelerator を使用する場合、ログ内の cache server= の件数が 0 より大きいこと。

数値

値対象出典
5.6~6.7 秒593 ファイルを 1 回のバッチでコピーおよびインポート実測
19.0 秒 対 5.1 秒195 個の FBX に対する 2 回のリマップパス(SaveAndReimport)。1 件ずつ処理する場合と 1 回のバッチで処理する場合実測
11~12 秒197 個のマテリアル、197 個の FBX リマップ、196 個のプレハブバリアント。エディター内の所要時間実測
1,717 インポート、52 秒/60 インポート別のプラットフォームでの初回起動/切り替え後に戻った場合(キャッシュ済みアーティファクト)実測
1,513 個のテクスチャ、17 秒何もしないテクスチャポストプロセッサーの GetVersion() を 1 回更新したことで再インポート実測
12,184 件をチェック、23.5 秒このプロジェクトの -consistencyCheck(7,390 件をスキップ。URP シェーダー 2 個にフラグ:ベースラインパッケージ)実測
0 ファイル2 回目の全実行(インポート、プレハブ、グループ)で変更されたファイル実測
791 件のテスト、10~16 秒196 個のプレハブ、396 個のテクスチャ、197 個のモデルに対するコンテンツテスト実測
13.5/12.9/4.8 MB最大ラベル読み込み量。カテゴリ/分離/条件レイアウト(3 つのバイオーム)実測
5カテゴリレイアウト内の重複アセット(テクスチャ 2 個、Lit.shader、フォールバック 2 個)実測
0~63 ミリ秒最後の Release 後もロードされたままのバンドル(7 回のプレイヤー実行)実測
60~158 秒/5~23 秒初回の macOS Mono プレイヤービルド/増分リビルド(共有マシン)。プレイヤーは 127.4 MB実測
0.4~1.2 秒 対 10~17 秒常駐エディターのブリッジ経由で実行した同じジョブと、エディター起動を伴うバッチジョブ実測
4 GBクロスプラットフォーム互換性のためのバンドルあたりの上限Addressables 2.9 マニュアル
30,000 頂点FBX の予算に関する警告の例Unity チュートリアル、qZ5NmyoxKRk [00:03:55]
38%、約 110 MBストリーミングによる Valheim のメモリ削減量、およびロード済みバンドルの削減によるメモリ削減量Axelsson [00:03:02]、[00:30:41]
179 秒/486 秒Library/ のないチェックアウトから生成した ci/pipeline.sh(v0.2、低負荷のマシン/v0.1、ほかにエディター 6~8 個)実測
0/8/6unity test の終了コード:成功/テスト失敗(再試行しない)/判定なし(再試行)unity-cli スキル

品質ゲート

  • 測定可能: エンベロープの ok、コンパイルエラーなし、すべてのステージで active_target が一致していること、ImportDrop のカウント、Assets/ 配下の整合性チェックがクリーンであること、プレハブ数、再実行時のコピー数が 0 であること、git status がクリーンであること、implicit_duplicates が 0 で duplicated_assets が 0 であること、ラベルごとの KB、Addressable コンテンツをハード参照するビルドシーンがないこと、NUnit の失敗数が 0 で期待される合計数と一致すること、AGENT_GATE が正常であること、BuildReport が Succeeded であること、プレイヤーのスモークテストのカウント、リリース時にツリーがクリーンであること、プロベナンスの source.dirty が false であること、禁止された定義がないこと、クリーンなチェックアウトから CI スクリプトを実行した際の終了コードが 0 であること。
  • 視覚: 配置シートを開き、マゼンタ色ではないこと、法線マップで陰影が付いていること、プロップが直立していること、ピボットが地面にあること、1.8 m のカプセルと並べたときに妥当なサイズであることを確認します。

よくある間違い

間違い発生する問題対処法
OnPostprocessTexture でインポーター設定を変更し、コードを変更しても GetVersion() を更新しない古い設定が使われ、マシン間で動作が異なるOnPreprocess* を使い、バージョンを更新して -consistencyCheck を実行する
ルール JSON にインポーター以外のキーを追加する管理対象のアセットがすべて再インポートされる別ファイル(pipeline_checks.json)に分ける
移動する前に Undo.RecordObject(gameObject) を呼び出す移動を元に戻せないTransform を記録する
Prefab インスタンスまたは ScriptableObject に直接書き込む次回の Prefab 更新時に変更が戻る/ファイルが変更されないRecordPrefabInstancePropertyModifications / SetDirty を使う
finally を使わずに StartAssetEditing を呼び出す。バッチ外で FBX ごとに SaveAndReimport を呼び出すデータベースがフリーズする。リマップが 4 倍遅くなるtry/finally を使い、バッチ内で再インポートする
各ステージで異なる -buildTarget を指定するステージごとにテクスチャとシェーダーが再インポートされるテストを含むすべてのステージで同じターゲットを指定する
共有テクスチャのあるフォルダーごとにグループを作成する同じテクスチャとシェーダーが各バンドルに含まれる条件付きパッキングを使用し、ビルドレイアウトを確認する
ファイル内または HashSet の順序でラベルを追加するマシンごとに設定ファイルの内容が異なる序数順に並べる
ビルドシーンから Addressable Prefab を参照する二重にロードされ、バンドルが迂回されるゲートで HardReferences を確認する
コンテンツをビルドしてから、デフォルトのプレイヤービルドを行うコンテンツが再ビルドされ、アーカイブ済みの状態が古くなるDoNotBuildWithPlayer とゲートを使う
バッチジョブで SetActiveBuildProfile を使う。内部 API のプロファイルを使うターゲットまたは定義が古くなり、アップグレード時に壊れる-activeBuildProfile を使い、コミット済みのテンプレートをコピーする
インポーターがエラーをログに出力するアセットをテストで再インポートする"Unhandled log message" が発生し、テストが失敗するLogAssert.Expect を使う
テスト用 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) の後に 2 つのプロバイダータイプを設定する
-runTests とともに -quit を指定する。相対パスの --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 では Content Directories が AssetBundle ビルドに置き換わります。
  • IPreprocessBuildWithContext は AssetBundle ビルドでも実行されます。BuildPipeline.isBuildingPlayer でフィルタリングしてください。
  • 6.5 より前には、プロファイルを作成する公開 API はありません。AssetDatabase カウンターは UnityEditor.Experimental.AssetDatabaseExperimental.counters で公開されています。
  • Unity CLI はベータ版です。unity build は macOS ではプロベナンスマニフェストを .app 内に書き込みます。Personal ライセンスのアクティベーションは Hub へのサインインでのみ行えます。

参考資料

コメント