Claude Media
Claude CodeでUnityゲーム開発を進める — C#スクリプトとコマンドライン検証

Claude CodeでUnityゲーム開発を進める — C#スクリプトとコマンドライン検証

Claude CodeはUnity Editorを直接操作しません。CLAUDE.mdにMonoBehaviourの規約を書き、バッチモードでコンパイル・テスト・ビルドを検証する手順を扱います。

Claude CodeとUnity開発の役割分担

Claude CodeはUnity Editorを直接操作するGUIツールではありません。得意なのはC#スクリプトの編集と、コマンドラインでのコンパイル確認・テスト実行・ビルドです。Unity Editorには-batchmode-runTestsといった引数が用意されており、エディタ画面を開かなくてもスクリプトの健全性を検証できます。この検証ループを権限設定とフックに組み込めば、書かせたC#スクリプトがコンパイルを通るかをその場で確認できます。

シーンの組み立てやプレハブの配線、ライティング調整といったEditor GUI上の作業はClaude Codeの守備範囲外です。この領域まで自動化したい場合は、Unity Editorに組み込まれたMCPブリッジをClaude Codeに接続するUnity公式MCPサーバーをClaude Codeで使う方法が別の選択肢になります。本記事はMCPサーバーを使わず、CLAUDE.mdとコマンドライン引数だけでC#スクリプトのゲームロジックを書き進める手順に絞ります。

前提条件

次の2点を先に整えておきます。

  • Unity Editor(Unity 6系、6000.x)でプロジェクトを一度は開いたことがある。本記事はUnity 6.6のマニュアルに基づきます
  • Claude CodeのBash権限で、Unity Editorの実行ファイルパスへのコマンド実行を許可している(手順はステップ3で扱います)

ステップ1: CLAUDE.mdにMonoBehaviourの規約を書く

UnityのスクリプトはMonoBehaviourクラスを継承したC#ファイルとして書きます。Claude Codeに規約を渡さないと、一般的なC#クラスの流儀でコンストラクタを書いてしまうことがあります。Unity公式マニュアルは、MonoBehaviourの初期化にコンストラクタを使うとUnityの通常動作を妨げると明記しています。

CLAUDE.mdには次のような規約を書いておきます。

## Unityスクリプトの規約
 
- MonoBehaviourを継承するクラスにコンストラクタを書かない。初期化は`Awake``Start`で行う
- `Start`はゲームプレイ開始前に一度だけ呼ばれる。変数の初期化や他オブジェクトとの参照解決はここに書く
- `Update`は毎フレーム呼ばれる。移動や入力処理などフレームごとの処理はここに書く
- クラス名とファイル名を一致させる
- 同じイベント関数でも、異なるGameObject間・同じスクリプトの異なるインスタンス間で呼び出し順序は保証されない。順序に依存するロジックは書かない

最後の1行は見落としやすい制約です。Unity公式マニュアルは、同じイベント関数が呼ばれる順序を異なるGameObject間で当てにできないと明記しています。あるオブジェクトのUpdateが別オブジェクトのUpdateより必ず先に呼ばれる、という前提でロジックを書くと、Editorやプラットフォームによって挙動が変わる不具合になります。

ステップ2: ゲームロジックをC#スクリプトとして書かせる

規約を渡したうえで、具体的な指示を出します。例えば「プレイヤーの左右移動を実装するPlayerMoverスクリプトを作って」と依頼すると、次のような形のスクリプトが返ってきます。

using UnityEngine;
 
public class PlayerMover : MonoBehaviour
{
    [SerializeField] private float moveSpeed = 5f;
 
    private void Update()
    {
        float horizontal = Input.GetAxis("Horizontal");
        transform.Translate(Vector3.right * horizontal * moveSpeed * Time.deltaTime);
    }
}

StartAwakeを使わずコンストラクタを書いていない点、Updateにフレームごとの処理をまとめている点が規約どおりです。Unity 6.6のC#コンパイラはRoslynで、対応言語バージョンはC# 9.0です。C# 10以降で追加された構文(ファイルスコープ名前空間やrequired修飾子など)を書かせると、コンパイルエラーになります。最近のC#構文に慣れたモデルほど踏みやすい落とし穴なので、CLAUDE.mdに「C# 9.0までの構文を使う」と明記しておくと安全です。

サンプルで使ったInput.GetAxisはレガシーのInput Managerが提供するAPIです。Unity公式マニュアルは、Input Managerはレガシー機能であり新規プロジェクトには推奨しないとし、新規プロジェクトにはInput Systemパッケージの使用を案内しています。既存プロジェクトがどちらを使っているかはClaude Codeからは判別できません。CLAUDE.mdに「このプロジェクトはレガシーInput Managerを使う」か「Input SystemパッケージのInputActionを使う」かを明記しておくと、書かせるコードの入力処理が食い違いません。

ステップ3: バッチモードでコンパイルとテストを検証する

Unity Editorは-batchmodeを付けて起動すると、ダイアログ表示なしでコマンドライン引数だけを処理します。まずBash権限で実行ファイルへのコマンドを許可します。

{
  "permissions": {
    "allow": [
      "Bash(/Applications/Unity/Hub/Editor/*/Unity.app/Contents/MacOS/Unity -batchmode *)"
    ]
  }
}

ワイルドカードはサブコマンドより後ろに置きます。Claude Codeの権限ルールは*より前の文字列をそのまま照合するため、-batchmodeより前を固定した書き方が安全です。設定の詳細はBash権限ルールの複合コマンド判定で扱っています。

コンパイルエラーの有無は、プロジェクトを開いて即座に終了させ、ログファイルを読む形で確認します。

"/Applications/Unity/Hub/Editor/6000.6.0f1/Unity.app/Contents/MacOS/Unity" \
  -batchmode -quit -nographics \
  -projectPath . \
  -logFile /tmp/unity-check.log
echo "exit code: $?"
cat /tmp/unity-check.log | grep -i "error CS"

バッチモード中は例外が発生するとUnityが終了コード1で終了します。-logFileに出力したログをerror CSでgrepすれば、C#コンパイラが吐いたエラー番号付きのメッセージを拾えます。バッチモードのコンソール出力は最小限に絞られる一方、ログファイルには全情報が残る仕様なので、ログファイルを読む前提で組んでおきます。

テストを回す場合はUnity Test Frameworkのコマンドライン引数を使います。

"/Applications/Unity/Hub/Editor/6000.6.0f1/Unity.app/Contents/MacOS/Unity" \
  -runTests -batchmode \
  -projectPath . \
  -testPlatform EditMode \
  -testResults /tmp/unity-test-results.xml

-testPlatformEditModePlayMode、または特定のビルドターゲットを指定します。未指定ならEdit Modeテストが走ります。-testfilterで対象テストを名前や正規表現で絞り込め、-assemblyNamesでテストアセンブリをセミコロン区切りで指定できます。結果はNUnit形式のXMLとして-testResultsのパスに出力されるので、Claude Codeにこのファイルを読ませて失敗内容を伝えれば、修正の材料になります。

ステップ4: コマンドラインでビルドする

Playerのビルドもコマンドラインから実行できます。必須の引数は-projectPath-quit、推奨されるのは-batchmode-logFile、それに-buildTarget-activeBuildProfileです。

"/Applications/Unity/Hub/Editor/6000.6.0f1/Unity.app/Contents/MacOS/Unity" \
  -batchmode -quit \
  -projectPath . \
  -buildTarget StandaloneOSX \
  -executeMethod BuildScripts.BuildMacOS \
  -logFile /tmp/unity-build.log

-executeMethodにはビルド処理を書いた静的メソッドを渡します。Unity公式マニュアルは、1回のコマンド実行で複数のビルドターゲットを切り替えられない点を明記しています。プラットフォームを変えると内部でエディタアセンブリの再読み込みが発生し、スクリプト実行中にその切り替えが反映されないためです。Windows向けとmacOS向けを両方ビルドしたい場合は、ターゲットごとにUnityプロセスを分けて起動します。

Claude CodeのフックでUnity検証を自動化する

C#ファイルを編集するたびに手動でバッチモードコマンドを打つのは手間です。PostToolUseフックにEdit(*.cs)という条件を付けると、Claudeが.csファイルを編集した直後にだけ検証スクリプトを走らせられます。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "if": "Edit(*.cs)",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/unity-compile-check.sh"
          }
        ]
      }
    ]
  }
}

ifフィールドはBashの権限ルールと同じ書式でツール呼び出しを絞り込みます。unity-compile-check.shの中身は、ステップ3の-batchmode -quit -logFileコマンドとログのerror CS検索をまとめたシェルスクリプトです。終了コードが1ならフックがエラーを返し、Claudeはログの内容を読んで修正に進みます。失敗するテストを起点に実装を進める考え方はClaude Codeでテスト駆動開発(TDD)を回す手順とも重なるので、あわせて確認すると設計の参考になります。フックの仕組み自体はClaude Code Hooks完全ガイドにイベント一覧があります。

CLIワークフローとUnity公式MCPサーバーの使い分け

同じ「Claude CodeでUnityを触る」でも、CLIバッチモードとUnity公式MCPサーバーでは向いている作業が違います。

作業CLIバッチモード(本記事)Unity公式MCPサーバー
C#スクリプトの編集・コンパイル確認CLIバッチモード(本記事)◎ ログファイルで確認できるUnity公式MCPサーバー△ Editorを開く前提
Unit Test Frameworkのテスト実行CLIバッチモード(本記事)-runTestsでCI的に回せるUnity公式MCPサーバー△ 対応する組み込みツールはない
シーン編集・プレハブ配線CLIバッチモード(本記事)× Editor GUIの操作は不可Unity公式MCPサーバー◎ 組み込みツールで自動化できる
コンソールログの読み取りCLIバッチモード(本記事)△ ログファイル経由で間接的Unity公式MCPサーバーUnity_ReadConsoleで直接取得
CI/CDへの組み込みCLIバッチモード(本記事)◎ Editorを起動せず完結Unity公式MCPサーバー△ Editorプロセスの常時起動が前提

C#スクリプトの実装とコンパイル確認を繰り返す局面ではCLIバッチモードが手早く、シーンやアセットをEditor越しに触りたい局面ではMCPサーバーに分があります。両方を併用し、ロジックの実装はCLIで、シーンへの配置はMCPサーバー経由で進める組み合わせも成立します。

よくあるつまずき

MonoBehaviourにコンストラクタを書いてしまうケースが最も多い落とし穴です。一般的なC#の作法に引っ張られると発生しやすく、CLAUDE.mdへの明記だけでなく、レビュー時にpublic PlayerMover()のようなコンストラクタが混ざっていないか目視で確認すると安心です。

イベント関数の実行順序に依存したロジックを書いてしまう場合もあります。あるスクリプトのStartで別のGameObjectの初期化済み状態を前提にすると、順序が入れ替わったときだけ発生する不具合になります。参照解決はAwake、他オブジェクトに依存する処理はStartに分けるのが基本です。

-batchmodeを付け忘れてダイアログで止まるのもよくある失敗です。保存確認などのダイアログはバッチモードでのみ自動的に抑制されるため、CI環境で実行する場合は必須の引数として扱います。

複数プラットフォームを1回のコマンドでビルドしようとすると、2つ目以降のビルドターゲット切り替えが反映されずに失敗します。プラットフォームごとにUnityプロセスを分けて呼び出します。

C# 9.0で使えない構文を書かせてしまうのも見落としがちです。Unity 6.6のRoslynコンパイラはC# 9.0までの対応で、それより新しい構文はコンパイルエラーになります。エラーログに見慣れない構文絡みのメッセージが出たら、まず言語バージョンを疑います。

まとめ

Claude CodeでUnityゲームを作る基本形は、CLAUDE.mdにMonoBehaviourの規約(コンストラクタ禁止・実行順序への非依存)を書くことです。そのうえでC#スクリプトを編集させ、-batchmodeを付けたコマンドラインでコンパイルとテストをその場で確認します。-runTestsによるテスト実行と-executeMethodによるビルドを組み合わせれば、Editorを開かずに一通りの検証がCLIだけで完結します。フックで検証コマンドを自動実行させれば、C#ファイルを編集するたびに人手を挟まず確認できます。シーンやプレハブなどEditor GUI側の操作まで自動化したくなったら、Unity公式MCPサーバーの利用を検討してください。

この記事を共有:XはてブLinkedIn