UnityEditorをCLIで操作するツールを作った
概要
Unity Editorをターミナルから操作するためのツールを作ったので紹介します。
なぜ作ったか
Unity開発でコーディングエージェントを使う上で、 UnityMCPのようなMCPツールでUnityを操作できるようにするのが一般的かと思います。
コンソールをコピペすることもなくなり、 非常に便利で実際に開発で利用していました。
ただ、 自分の使い方では以下の課題もありました。
- MCPは常駐型の設計
- コーディングエージェントが常にツールにアクセスできる反面、 コンテキストウィンドウを常時消費(実測18.4kトークン)
- 実験していた当時のスクラップはこちら
- 開発者自身もエディタをCLIから操作したい
- コーディングエージェント主体の開発スタイルになるほど、ターミナルであらゆる作業を完結させたくなる
- エラーログを読ませて分析させるとき、 「エラーログを読んで」と指示するところから始めるより
!unity console getのように直接コマンドを実行してコンソールのログをコンテキストに渡すところから始めた方が確実
そこで、 UnityMCPの基本的な仕組みを参考にしつつCLI用途に対応させる方針で作ることにしました。
インストール
Unity
Unity Package Managerから以下のURLでインストールできます。
https://github.com/bigdra50/unity-cli.git?path=UnityBridge
またはOpenUPMを使う場合
$ openupm add com.bigdra50.unity-bridge
CLI
uvxで直接実行
# プレイモード制御
$ uvx --from git+https://github.com/bigdra50/unity-cli u play
$ uvx --from git+https://github.com/bigdra50/unity-cli u stop
# コンソールログ取得
$ uvx --from git+https://github.com/bigdra50/unity-cli u console get -l E
グローバルインストール
$ uv tool install git+https://github.com/bigdra50/unity-cli
インストール後はunity-cli, u, unityの3つのエイリアスが使えます
$ unity-cli state
$ unity state
$ u state
シェル補完も利用できます
# zsh
$ u completion -s zsh > ~/.zsh/completions/_unity-cli
# bash
$ u completion -s bash >> ~/.bashrc
# fish
$ u completion -s fish > ~/.config/fish/completions/unity-cli.fish

使い方
unity-cliのコマンドは大きく2つに分かれます。
UnityEditor起動不要のコマンド
プロジェクト情報の取得
$ u project info
╭──────────────────────────────────────────────────╮
│ MyGame │
╰────── /Users/username/Projects/MyGame ───────────╯
Company: MyCompany
Version: 1.0.0
Unity: 2022.3.20f1
Unityバージョンだけ取得したい場合:
$ u project version
Unity: 2022.3.20f1
インストール済みUnityエディタの管理
$ u editor list
Installed Editors (2)
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Version ┃ Path ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╩
│ 2023.2.10f1 │ /Applications/Unity/Hub/Editor/… │
│ 2022.3.20f1 │ /Applications/Unity/Hub/Editor/… │
└──────────────┴──────────────────────────────────┘
プロジェクトを開く
git clone後などよく使います。
# Unity Editorでプロジェクトを開く
$ u open
# 特定バージョンで開く
$ u open --version 2022.3.20f1
設定の確認
$ u config show
=== Unity CLI Configuration ===
Config file: Not found (using defaults)
Relay host: 127.0.0.1
Relay port: 6500
Timeout: 15.0s
Instance: (default)
UnityEditor起動が必要なコマンド
Unity Editorが起動した状態でRelay Serverを介して操作するコマンドです。
以下のコマンドを使う前に、Relay Serverの起動と接続が必要です。
Relay Serverの起動
Unity Editorで Window > Unity Bridge を開き、Start Server → Connect の順にクリックします。

StatusがConnectedになれば準備完了です。
接続状態はエディタ右上のツールバーバッジからも確認できます。バッジをクリックすると接続・切断の切り替えも可能です。

CLIから直接Relay Serverを起動することもできます。
$ uvx --from git+https://github.com/bigdra50/unity-cli unity-relay --port 6500
Relay Serverは1つのプロセスで複数のUnityインスタンスからの接続を受け付けます。
複数のUnityプロジェクトを同時に開いている場合でも、各インスタンスから同じサーバーにConnectするだけでよく、サーバーを2重に起動する必要はありません。
操作対象のインスタンスは u instances で確認し、-i オプションで指定できます。
# 接続中のインスタンス一覧
$ u instances
Connected Instances (1)
┏━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━┓
┃ # ┃ Project ┃ Unity Version ┃ Status ┃ Default ┃
┡━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━┩
│ 1 │ TestProject │ 6000.2.6f2 │ ready │ * │
└───┴─────────────┴───────────────┴────────┴─────────┘
# インスタンスを指定してコマンド実行
$ u -i TestProject state
C#スクリプトのコンパイル確認
スクリプト編集後、コンパイルエラーがないか確認する流れ:
# AssetDatabaseをリフレッシュしてコンパイル実行
$ u refresh
[OK] Asset database refreshed
# エラーがあれば表示される
$ u console get -l E
06:53:37 error Assets/Scripts/Player/PlayerHealth.cs(44,13): error CS0201: Only
assignment, call, increment, decrement, await, and new object expressions can be
used as a statement
06:53:37 error Assets/Scripts/Player/PlayerHealth.cs(44,13): error CS0103: The
name 'hoge' does not exist in the current context
# エラー修正後、コンソールをクリアしてから再コンパイル
$ u console clear
[OK] Console cleared
$ u refresh
[OK] Asset database refreshed
# エラーなし = 出力なし
$ u console get -l E
-v オプションでスタックトレース付き表示も可能です。ランタイムエラーの調査に使えます:
$ u console get -l E -v
テストの実行
EditModeテスト:
# テスト一覧を確認
$ u tests list edit
{
"mode": "edit",
"count": 38,
"tests": [
{ "fullName": "Game.Tests.Editor.DamageCalculatorTests.Calculate_AppliesCriticalMultiplier_WhenCritical", ... },
{ "fullName": "Game.Tests.Editor.InventoryTests.AddItem_IncreasesSlotCount_WhenNewItem", ... },
...
]
}
# テスト実行
$ u tests run edit
Running tests (46/46) Pass:38 Fail:0 Skip:0
PlayModeテスト:
$ u tests list play
$ u tests run play
Running tests (17/17) Pass:19 Fail:0 Skip:0
menu execで使い捨てスクリプトを実行する
menu execはMenuItemをCLIから実行するコマンドです。 既存のMenuItemの実行にも使えますが、使い捨てスクリプトを書かせて実行させるのも便利です。
unity-cliの各コマンドではカバーしきれないEditorAPI操作を頼みたいとき、エージェントに[MenuItem]付きのスクリプトを書かせてmenu execで実行させます。
例えば、 シーンへのオブジェクト配置やインスペクター操作が必要な作業などがあります。
# 1. エージェントが [MenuItem("Tools/TempSetup")] 付きスクリプトを生成
# 2. コンパイル→実行→後片付け
$ u refresh
$ u menu exec "Tools/TempSetup"
$ rm Assets/Editor/TempSetup.cs && u refresh
EditorAPIで可能なことなら何でもこの方法で実行できるので、CLIに専用コマンドがない操作の受け皿になります。
コーディングエージェントとの連携
エージェント向けのエラーメッセージ
コーディングエージェントが自律的にコマンドを実行していく上で、エラー発生時にリカバリしやすいようエラーメッセージには次のアクションを含めるようにしています。
# Playモードでないのにpauseしようとした場合
$ u pause
Error: Cannot pause: not in play mode. Enter play mode first with action 'enter'.
# 不正なアクションを渡した場合
$ u play --action foo
Error: Unknown action: foo. Valid actions: enter, exit, pause, unpause, step, state
# 接続先インスタンスが見つからない場合
$ u state
Error: Instance not found. Check available instances with 'u instances'.
エージェントはエラーメッセージを読んで次に実行すべきコマンドを判断できるため、人間の介入なしにリカバリを進められます。
連携例: UIの作成からスクリーンショットまで
以下はClaude Codeに「UI Toolkitでニューモーフィズム風のゲームタイトル画面を作って、シーンに配置して、スクリーンショットを撮って」と指示した際の実行ログです。UXML/USS/C#の作成からUnity上での動作確認まで、すべてClaude Codeが自律的に行っています。

UIToolKitで用意したデモ用のUI
# 1. UXML, USS, C#スクリプトをエージェントが作成した後...
# AssetDatabaseをリフレッシュしてコンパイル
$ u refresh
[OK] Asset database refreshed
# コンパイルエラーがないか確認
$ u console get -l E
(出力なし = エラーなし)
# シーンにGameObjectを作成してコンポーネントを追加
$ u gameobject create -n SampleHUD
$ u component add -t SampleHUD -T UnityEngine.UIElements.UIDocument
$ u component add -t SampleHUD -T SampleHUDController
$ u scene save
# PlayModeに入ってUIの表示を確認
$ u play
[OK] Entered play mode
# UIツリーをダンプして構造を確認
$ u uitree dump -p "PanelSettings" -d 3
Panel: PanelSettings (36 elements)
VisualElement "Root" .root ref_3
VisualElement "StatusBar" .status-bar ref_4
Label "StatusTime" ref_5
VisualElement "TitleCard" .neu-card .profile-card ref_6
VisualElement .title-area ref_7
VisualElement .xp-section ref_10
VisualElement "Chapters" .section ref_22
Label .section-title ref_23
VisualElement .card-row ref_24
VisualElement "Menu" .section ref_46
VisualElement .action-row ref_47
VisualElement "Toast" .toast .hidden ref_54
Label "ToastMessage" ref_55
VisualElement "TabBar" .neu-card .tab-bar ref_57
VisualElement "TabHome" .tab .tab-active ref_58
VisualElement "TabQuest" .tab ref_60
VisualElement "TabCodex" .tab ref_62
VisualElement "TabConfig" .tab ref_64
# GameViewのスクリーンショットを撮影
$ u screenshot -s game -p ./screenshot.png
[OK] Screenshot captured: ./screenshot.png
$ u stop
[OK] Exited play mode
連携例: UIツリーの探索とインタラクション
uitreeコマンドはPlaywright MCPに似たref IDベースの操作体系で、UI Toolkitの要素を検索・検査・操作できます。
以下はClaude Codeに次のプロンプトを渡した際のセッションの例です。
Claude Codeがdump→query→text→click→inspectのサイクルを自律的に回しています。
Playモードに入って、unity-cliのuitreeコマンドでUI Toolkit要素を探索してください。
UIツリーの構造把握、要素の検索・検査・テキスト取得、クリック操作による状態変化の検証まで一通り試してください。
# Playモードに入ってパネル一覧を取得
$ u uitree dump
Panels:
[Editor] DockArea (21 elements)
[Editor] Toolbar (76 elements)
[Player] PanelSettings (65 elements)
[Player] UIDocument SamplePanelSettings (SampleHUD) (64 elements)
...
# UIツリーの構造をダンプ (ref IDが各要素に割り振られる)
$ u uitree dump -p "SampleHUD" -d 3
Panel: UIDocument SamplePanelSettings (SampleHUD) (20 elements)
UIDocumentRootElement "SampleHUD-container" ref_1
VisualElement "Root" .root ref_2
VisualElement "StatusBar" .status-bar ref_3
VisualElement "TitleCard" .neu-card .profile-card ref_4
VisualElement .title-area ref_5
VisualElement .xp-section ref_8
VisualElement "Chapters" .section ref_15
Label .section-title ref_16
VisualElement .card-row ref_17
VisualElement "Menu" .section ref_18
VisualElement .action-row ref_19
VisualElement "Toast" .toast .hidden ref_20
VisualElement "TabBar" .neu-card .tab-bar ref_21
# ref IDでテキスト読み取り
$ u uitree text ref_167
ref_167 Label: Story Progress
$ u uitree text ref_197
ref_197 Label: SETTINGS
# 型で要素を検索
$ u uitree query -p "SampleHUD" -t Label
Found 29 elements in "SampleHUD":
ref_147 Label "StatusTime" ...
ref_148 Label .game-title ...
...
# 子要素付きで検査 → Chapter1がcard-selectedを持っていることを確認
$ u uitree inspect ref_171 --children
ref_171 VisualElement "Chapter1"
classes: .neu-card .featured-card .card-selected
visible: True
...
# Chapter2をクリックして選択状態の変化を検証
$ u uitree click ref_178
ref_178 VisualElement: Clicked element
$ u uitree inspect ref_178
ref_178 VisualElement "Chapter2"
classes: .neu-card .featured-card .card-selected # ← 選択が移動した
...
# タブをクリック → tab-activeの移動を確認
$ u uitree click ref_155
ref_155 VisualElement: Clicked element
$ u uitree inspect ref_155
ref_155 VisualElement "TabQuest"
classes: .tab .tab-active # ← tab-activeが付与された
...
# CONTINUEボタンクリック → Toastメッセージ確認
$ u uitree click ref_192
ref_192 VisualElement: Clicked element
$ u uitree text ref_153
ref_153 Label: Loading save data...
dump → click → inspect/text のサイクルで、Claude CodeがUI操作とその結果検証を自律的に回せます。
Claude Codeにコマンドを教える
MCPのように常時コンテキストを消費しない代わりに、Claude Codeにコマンド体系を知らせる手段が必要です。基本的にはプロジェクトのCLAUDE.mdによく使うコマンドを簡潔に書いておくだけで事足りています。
## Commands
| コマンド | 用途 |
| -------------------------------- | ------------------------- |
| `u state` | エディタ状態の取得 |
| `u play` / `u stop` | Play/Stopモード制御 |
| `u refresh` | AssetDatabaseリフレッシュ |
| `u console get -l E` | エラーログの取得 |
| `u tests run edit` | EditModeテスト実行 |
| `u uitree dump -p <panel>` | UIツリーのダンプ |
| `u screenshot -s game -p <path>` | スクリーンショット撮影 |
ただし、「refresh→コンパイルエラーチェック→テスト→ランタイム確認」のような一連のワークフローまでCLAUDE.mdに書き出すと、結局コンテキスト消費が増えて本末転倒です。
そこで、ワークフロー単位の手順はSkillとして切り出しています。
Skillは呼び出し時にのみコンテキストに読み込まれるため、常時消費を避けつつ複雑な手順をエージェントに渡せます。
これらのSkillは試験的にClaude Codeプラグイン化しています。
# マーケットプレイスから追加
/plugin marketplace add bigdra50/unity-cli
# インストール
/plugin install unity-cli@unity-tools
最後に
コーディングエージェント周辺のツールチェーンは変化が速く、今の設計が半年後も最適とは限りません。
実際に使いながら必要な機能を追加・改善していくつもりです。
Skillはプロジェクト固有のワークフローに依存する部分が多いため、当面はCLI本体の機能拡充を優先していく方針です。
Issue・PRは歓迎です。使ってみて気づいたことがあればぜひフィードバックをお待ちしています。
追記(2026-02-11): Relay Serverの起動手順・ツールバーバッジによる接続確認・複数インスタンス接続時の補足を追加しました。
Discussion