mcpField
U
unity-package-management

unity-package-management

github.com/unity-technologies開発60461 回インストール今日更新
リポジトリ

unity-package-management について

unity-package-managementは、Unity Package Managerのパッケージを追加、削除、更新、検索するスキルです。プロジェクトのPipelineパッケージのコマンドを優先し、Editorを使えない場合のヘッドレスC#方式も説明します。

主な機能

  1. 01UPMパッケージの追加、削除、更新
  2. 02パッケージ検索とバージョン確認
  3. 03Pipelineパッケージのコマンドを優先
  4. 04必要に応じたヘッドレスC#方式
  5. 05インストール後のパッケージ検証

活用シーン

  1. 01既存のUnityプロジェクトの依存関係管理
  2. 02CIでの非対話型パッケージ設定
  3. 03パッケージIDと利用可能なバージョンの確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/unity-technologies/unity-agent-plugin --skill unity-package-management

インストール後、Claude Code で/unity-package-managementを入力して読み込まれたか確認します。

同梱ファイルreferences/select-packages.md

詳細

Unity パッケージ管理(まず Pipeline コマンドを使用し、C# スクリプトはフォールバックとして使用)

プロジェクトの Pipeline パッケージの package コマンドを unity command で実行して、UPM(Unity Package Manager)パッケージの追加、削除、アップグレード、検索を行います。これらのコマンドに対応できる Editor がない場合に限り、スクリプトから UnityEditor.PackageManager.Client をヘッドレスで操作する方法に切り替えます(フォールバックを参照)。Packages/manifest.json を直接編集しないでください。Package Manager は依存関係と互換性のあるバージョンを正しく解決しますが、手動編集では解決が頻繁に壊れます。

この内容は、Editor のインストール、プロジェクトの作成、ビルド/テストを扱う unity-cli スキルを補完するものです。このスキルでは unity command、unity status、unity pipeline install について説明しています。

まず package コマンドを使用する

Pipeline パッケージは add、remove、list、resolve、search、status の package コマンドグループを登録します。これらを使うには、プロジェクトに com.unity.pipeline が追加された、Editor の起動中のプロジェクトが必要です(unity pipeline install で追加し、次に unity open を実行してから、unity status --until-ready で準備完了を待ちます)。各コマンドのパラメーターは Editor から取得するため、最初に呼び出す前に確認してください。パラメーター名を推測しないでください。

unity status --until-ready --project-path "<project-path>"
unity command package --project-path "<project-path>"                  # the package commands this Editor has
unity command --query package --format json --project-path "<project-path>"   # each command's parameter schema
unity command package search --project-path "<project-path>"           # then pass the parameters the schema lists
unity command package add --project-path "<project-path>"              # add one or more packages by id
unity command package list --project-path "<project-path>"             # confirm what is installed

コマンド名の後に、そのスキーマで定義された名前のパラメーターを渡します(unity command <group> <command> --<parameter> <value>)。スキーマが複数の ID を受け付ける場合は、必要なパッケージをすべて 1 回の package add 呼び出しで追加します。最小バージョンが必要な場合は、スキーマの説明に従ってバージョンを固定してください(@<version> ID 形式は、以下の C# フォールバックで使用します)。package status または package list で確認し、パッケージを削除するには package remove を使用します。ゼロ以外の終了コードは失敗として扱い、メッセージを確認してください。

unity command package がそのようなグループはないと報告した場合、プロジェクトの Pipeline パッケージは古いバージョンです。unity pipeline upgrade を実行するか、以下のフォールバックを使用してください。フォールバックは独自に Editor を起動するため、Editor でプロジェクトを開いている間は実行できません。まずユーザーに保存して閉じてもらってください(フォールバックの最初のルールを参照)。

使用する場面

  • 既存または新規作成したプロジェクトで、1 つ以上のパッケージを追加/削除/アップグレードするとき。
  • CI でプロジェクトのパッケージを非対話的に設定するとき(Editor が実行されていない場合はフォールバックのスクリプトを使用)。
  • パッケージ ID の存在を確認したり、依存する前に利用可能なバージョンを調べたりするとき。
  • ゲームで実際に必要なパッケージを選ぶとき。references/select-packages.mdを参照してください。

インストールするパッケージの選択

すべてではなく、プロジェクトで実際に必要なものをインストールしてください。選択したテンプレートにすでに含まれているパッケージを優先してください(URP テンプレートにはレンダーパイプライン、Input System などが含まれています)。ジャンル/見た目/プラットフォーム/収益化とパッケージの対応付け、およびレジストリの検索方法については、references/select-packages.mdを参照してください。インストールする前に、重複を除いたパッケージ ID のリストを作成し、ユーザーに読み上げて確認してください。

フォールバック:問い合わせる Editor がない場合(C# クライアント API)

package add を実行できない場合にのみ、このセクションを使用してください。Editor が開いておらず開くつもりもない場合、プロジェクトに Pipeline パッケージがない場合、またはコマンドグループが存在せずアップグレードも望まない場合が該当します。バッチモードで Editor が実行するスクリプトから Client.AddAndRemove を使ってインストールします。

最初にプロジェクトを閉じる必要があります。 スクリプトは 2 つ目のバッチモード Editor で実行されます。すでにプロジェクトを開いている Editor がロックを保持していると、スクリプトが始まる前にバッチ実行が失敗します。unity editors running --format json は、Pipeline パッケージの有無にかかわらず、開いているすべての Editor を一覧表示します(unity status が一覧表示するのは Pipeline プロジェクトのみなので、そちらの結果が空でもプロジェクトが閉じているとは限りません)。各 data.instances[].projectPath を対象プロジェクトと照合してください。また、<project-path>/Temp/UnityLockfile が存在するか確認し、プロジェクトが Editor で開かれているかユーザーに尋ねてください。Editor でプロジェクトが開かれている場合、または判断できない場合は、作業内容を保存して閉じるようユーザーに依頼し、閉じたという返答を待ってください。バッチ実行がロックによって引き続き失敗する場合は、プロジェクトが開いているものとして扱い、ユーザーに閉じるよう依頼してください。再試行したり、ロックファイルを削除したりしないでください。ユーザーの Editor を自分で閉じたり強制終了したりしてはいけません。未保存のシーンや Play Mode セッションがある可能性があります。ユーザーが Editor を開いたままにしたい場合は、フォールバックを実行しないでください。プロジェクトを閉じるか、Pipeline パッケージをアップグレードする(unity pipeline upgrade を実行してから package add を実行する)までインストールできないことを伝えてください。

-quit の問題 — インストールに unity run を使ってはいけない理由

Client.Add/Client.AddAndRemove は非同期です。後続の EditorApplication.update ティックでのみ完了する Request を返します(UPM の子プロセスは Editor のメインループのポンプを介して結果を返すため、while (!req.IsCompleted) でブロックしてビジーウェイトするとデッドロックします)。-executeMethod の戻り後も、リクエストが完了するまで Editor を起動したままにする必要があります。

インストーラーには unity run を使用できません。デフォルトでは -quit が挿入されるためです(予約済みフラグについては unity-cli スキルを参照してください)。-quit を指定すると、メソッドが戻った時点で Editor が終了し、UPM の解決前に処理が終わります。そのため、パッケージはインストールされず、コールバックも実行されません。

解決策: -quit を付けず、-batchmode を指定して Editor の実行ファイルを直接起動します。Editor は起動したままになり、EditorApplication.update が動き続けてポーリングコールバックが実行されます。完了時にはコールバックが EditorApplication.Exit(code) を呼び出します。これにより Editor が終了し、プロセスの終了コードも設定されます。

インストーラースクリプト

これを Assets/Editor/ProjectBootstrap/PackageInstaller.cs に書き込みます。UnityEditor を使用するため、Editor/ フォルダー内(または Editor 専用アセンブリ内)に置く必要があります。

using System.Linq;
using UnityEditor;
using UnityEditor.PackageManager;
using UnityEditor.PackageManager.Requests;
using UnityEngine;

namespace ProjectBootstrap
{
    // Installs (and optionally removes) a fixed set of packages via the PackageManager
    // Client API, headless-safe.
    public static class PackageInstaller
    {
        // EDIT this list to match the package selection (see references/select-packages.md).
        static readonly string[] PackagesToAdd =
        {
            "com.unity.inputsystem",
            "com.unity.cinemachine",
            "com.unity.render-pipelines.universal",
            // "[email protected]"  // pin a version with @ when a minimum is required
        };

        // Optionally drop packages in the same resolution pass (e.g. a template default you don't want).
        static readonly string[] PackagesToRemove = { };

        const double TimeoutSeconds = 600; // UPM resolution + downloads can be slow

        static AddAndRemoveRequest _request;
        static double _deadline;

        // Invoke with: -executeMethod ProjectBootstrap.PackageInstaller.Install  (NO -quit)
        public static void Install()
        {
            if (PackagesToAdd.Length == 0 && PackagesToRemove.Length == 0)
            {
                Debug.Log("[PackageInstaller] Nothing to do.");
                EditorApplication.Exit(0);
                return;
            }

            Debug.Log($"[PackageInstaller] Adding: {string.Join(", ", PackagesToAdd)}");
            _request = Client.AddAndRemove(packagesToAdd: PackagesToAdd, packagesToRemove: PackagesToRemove);
            _deadline = EditorApplication.timeSinceStartup + TimeoutSeconds;
            EditorApplication.update += Poll;
        }

        static void Poll()
        {
            if (_request == null) return;

            if (!_request.IsCompleted)
            {
                if (EditorApplication.timeSinceStartup > _deadline)
                {
                    EditorApplication.update -= Poll;
                    Debug.LogError("[PackageInstaller] Timed out waiting for UPM.");
                    EditorApplication.Exit(2);
                }
                return;
            }

            EditorApplication.update -= Poll;

            if (_request.Status == StatusCode.Success)
            {
                var names = _request.Result.Select(p => $"{p.name}@{p.version}");
                Debug.Log($"[PackageInstaller] Resolved: {string.Join(", ", names)}");
                EditorApplication.Exit(0);
            }
            else
            {
                Debug.LogError($"[PackageInstaller] Failed: {_request.Error?.message}");
                EditorApplication.Exit(1);
            }
        }
    }
}

AddAndRemove はセット全体を 1 回の UPM 解決処理でインストールします。パッケージごとに Client.Add を実行するより速く、エラーも少なくなります。

1 つのスクリプトで追加/削除/アップグレードする場合:

  • 追加:ID を PackagesToAdd に記載します。
  • 削除:ID を PackagesToRemove に記載します。
  • アップグレード/バージョン固定:@<version> を付けて ID を追加します(例:[email protected])。バージョンを指定しない場合、解決時に互換性のある最新リリースが選択されます。

パッケージの検出/検証

追加前に ID の存在を確認したり、バージョンを一覧表示したりするには、レジストリを検索します。Editor 内の Client.SearchAll()/Client.Search("<id>") 呼び出しも非同期のため、インストーラーと同じポーリングと Exit のパターン、および同じヘッドレス実行を使用します。Assets/Editor/ProjectBootstrap/PackageSearch.cs を作成します。

using System.Linq;
using UnityEditor;
using UnityEditor.PackageManager;
using UnityEditor.PackageManager.Requests;
using UnityEngine;

namespace ProjectBootstrap
{
    public static class PackageSearch
    {
        const double TimeoutSeconds = 120;
        static SearchRequest _request;
        static double _deadline;

        // Invoke with: -executeMethod ProjectBootstrap.PackageSearch.SearchAll  (NO -quit)
        public static void SearchAll()
        {
            _request = Client.SearchAll();                 // or Client.Search("com.unity.cinemachine")
            _deadline = EditorApplication.timeSinceStartup + TimeoutSeconds;
            EditorApplication.update += Poll;
        }

        static void Poll()
        {
            if (_request == null) return;
            if (!_request.IsCompleted)
            {
                if (EditorApplication.timeSinceStartup > _deadline)
                {
                    EditorApplication.update -= Poll;
                    Debug.LogError("[PackageSearch] Timed out.");
                    EditorApplication.Exit(2);
                }
                return;
            }
            EditorApplication.update -= Poll;

            if (_request.Status == StatusCode.Success)
            {
                foreach (var p in _request.Result.OrderBy(p => p.name))
                    Debug.Log($"[PackageSearch] {p.name}@{p.versions.latestCompatible}  {p.displayName}");
                Debug.Log($"[PackageSearch] {_request.Result.Length} packages found.");
                EditorApplication.Exit(0);
            }
            else
            {
                Debug.LogError($"[PackageSearch] Failed: {_request.Error?.message}");
                EditorApplication.Exit(1);
            }
        }
    }
}

_request.Result は PackageInfo[] で、各エントリには name、displayName、description、versions(.latest、.latestCompatible、.all)が含まれます。Editor を使わずにターミナルだけで確認する場合(自由入力検索ではなく、既知の ID が対象)は、レジストリに直接問い合わせてください。references/select-packages.md を参照してください。

ヘッドレスで実行する(-quit を使わずに Editor を直接呼び出す)

バージョンから Editor のバイナリを特定し、バッチモードで実行します。プロジェクトを開いている Editor がない場合にのみ実行してください(フォールバックの最初のルールを参照)。スクリプトが EditorApplication.Exit で終了するため、-quit は渡さないでください。

VERSION="<version>"          # e.g. 6000.0.47f1 (or an installed version)
PROJECT="<project-path>"
METHOD="ProjectBootstrap.PackageInstaller.Install"   # or ...PackageSearch.SearchAll

# Install directory of that editor (Hub layout), via the unity CLI
ED=$(unity editors path "$VERSION" --format json | python3 -c "import sys,json;print(json.load(sys.stdin)['data']['path'])")

# Resolve the executable per-OS (handles both "dir containing Unity.app" and the ".app" itself)
case "$(uname)" in
  Darwin) if [ -d "$ED/Unity.app" ]; then UNITY_BIN="$ED/Unity.app/Contents/MacOS/Unity";
          elif [[ "$ED" == *.app ]]; then UNITY_BIN="$ED/Contents/MacOS/Unity";
          else UNITY_BIN="$ED/Unity"; fi ;;
  Linux)  UNITY_BIN="$ED/Editor/Unity" ;;
  *)      UNITY_BIN="$ED/Editor/Unity.exe" ;;   # Windows (Git Bash / MSYS); use Editor\Unity.exe in PowerShell
esac

"$UNITY_BIN" -batchmode -projectPath "$PROJECT" -executeMethod "$METHOD" -logFile -
echo "Exit code: $?"   # 0 = success, 1 = UPM error, 2 = timeout

-logFile - を指定すると、Editor のログ([PackageInstaller]/[PackageSearch] の行を含む)が標準出力にストリーミングされるため、解決の進行状況を監視したり、UPM のエラーを確認したりできます。お使いのビルドで unity editors path の出力形式が異なる場合は、代わりに unity editors --installed --format json からディレクトリを取得してください。

確認

# Every requested id should appear as a dependency
cat "<project-path>/Packages/manifest.json"

実行が 0 で終了したこと、およびリスト内の各パッケージが manifest.json に存在することを確認します。パッケージの解決に失敗した場合は、_request.Error.message にログが記録されるため、その内容を読み、ID/バージョンがレジストリと一致しているか確認してください。Editor 自身のログ([PackageInstaller] の行を含む)は、上記の -logFile - でストリーミングした標準出力にあります。unity logs ではなく、そちらを確認してください(unity logs に表示されるのは CLI 自身のログであり、Editor のログではありません)。

ヘッドレスでインポートして保存する(.meta ファイルを生成する)

スクリプトまたはツールで新しい .cs/アセットファイルを書き込んだ後、Unity はそれらをインポートして、各アセットに必要な .meta ファイルを生成する必要があります。また、すべての .cs/アセットは対応する .meta と一緒にコミットする必要があります。プロジェクトを一度開くだけでも(unity open "<project-path>")、インポートと生成が行われます。この処理をヘッドレスで行う必要がある場合(スクリプトまたは CI 内)は、この方法を使ってください。

パッケージインストーラーと異なり、これは同期処理です。戻る前に完了するため、unity run 経由で安全に実行できます(挿入される -quit は問題ありません。このメソッドも正常な終了コードのために EditorApplication.Exit を呼び出します)。次のファイルを書き込みます。 Assets/Editor/ProjectBootstrap/ProjectSaver.cs:

using UnityEditor;
using UnityEngine;

namespace ProjectBootstrap
{
    public static class ProjectSaver
    {
        // Invoke with: -executeMethod ProjectBootstrap.ProjectSaver.SaveAll
        public static void SaveAll()
        {
            AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
            AssetDatabase.SaveAssets();
            Debug.Log("[ProjectSaver] Assets imported and saved.");
            EditorApplication.Exit(0);
        }
    }
}
unity run "<project-path>" --editor-version <version> \
  -- -executeMethod ProjectBootstrap.ProjectSaver.SaveAll

メモ

  • これらの Editor スクリプトは、ブートストラップを簡便にするためのものです。Assets/Editor/ProjectBootstrap/ に残しておいても(呼び出さない限り何もしません)、セットアップ後に削除しても構いません。判断はお任せします。ユーザーにその旨を伝えてください。
  • すべてのスクリプトは UnityEditor を使用するため Editor/ 以下に配置されています。ビルドに含まれることはありません。
  • マネタイズ/バックエンドのパッケージ(com.unity.purchasing、com.unity.services.levelplay、UGS パッケージ)も同じ仕組みでインストールしますが、実際の統合には専用のスキルを使ってください:implement-in-app-purchases、levelplay-unity-integration、build-live-game。

コメント