mcpField
U
unity-csharp-scripting

unity-csharp-scripting

github.com/gamedev-skills開発5.4k6.6k 回インストール今日更新
リポジトリ

unity-csharp-scripting について

Unity 6 で MonoBehaviour スクリプトを作成・修正する開発者向けの C# リファレンススキルです。ライフサイクル、コンポーネント参照、Inspector のシリアライズ、コルーチン、プロジェクト検査を扱います。

主な機能

  1. 01MonoBehaviour のライフサイクル指針
  2. 02コンポーネント参照のキャッシュ
  3. 03Inspector 向けシリアライズ
  4. 04コルーチンによる時間制御
  5. 05.meta と GUID のプロジェクト検査

活用シーン

  1. 01ゲーム動作に応じたコールバック選択
  2. 02デザイナー向け調整フィールドの公開
  3. 03遅延処理や順次処理の実装
  4. 04ファイル変更後のアセット参照確認

インストール

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

$npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill unity-csharp-scripting

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

同梱ファイルreferences/lifecycle-and-coroutines.mdscripts/check_unity_project.py

詳細

Unity C# スクリプティング(MonoBehaviour)

Unity 6 で正しく、慣用的なゲームプレイスクリプトを作成します。ライフサイクル、コンポーネントへのアクセス、シリアライズ、コルーチンを適切に扱い、動作を決定論的にして、インスペクターを便利に保ちます。対象は Unity 6.3 LTS (6000.3)、C# / .NET Standard 2.1 です。

使用する場面

  • MonoBehaviour の作成や修正時に使用します。適切なライフサイクルコールバックの選択、コンポーネントの取得やキャッシュ、インスペクターに表示するフィールドの設定、コルーチンを使った時間制御ロジックの実行などが対象です。
  • プロジェクトに *.cs ファイル、Assembly-CSharp または *.asmdef、および ProjectSettings/ フォルダーがある場合に使用します。

使用しない場面: リジッドボディの移動や衝突応答 → unity-physics、プレイヤー入力の読み取り → unity-input-system、共有データアセットや設定 → unity-scriptableobjects、Animator パラメーター → unity-animation。このスキルの対象はスクリプトのライフサイクルと C# の配線であり、これらのサブシステムではありません。

基本的なワークフロー

  1. 慣習ではなく目的に応じてコールバックを選択します。 Awake(参照をキャッシュし、ロード時に一度だけ実行)、OnEnable(イベントを購読)、Start(ほかのオブジェクトの Awake に依存する初期化)、Update(フレームごとのロジックや入力のポーリング)、FixedUpdate(物理演算)、LateUpdate(移動後のカメラ追従)、OnDisable/OnDestroy(購読解除やクリーンアップ)。
  2. コンポーネントの取得結果は Awake でキャッシュします — 毎フレーム GetComponent を呼び出してはいけません。
  3. 調整可能な値は [SerializeField] private で公開します。public フィールドではなく、ほかのコードから変更できない一方で、デザイナーがインスペクターで編集できるようにします。
  4. Update ではフレームごとの値に Time.deltaTime を掛けます(FixedUpdate では Time.fixedDeltaTime の意味が自動的に適用されます)。
  5. 時間順に実行するロジックにはコルーチンを使います(遅延、トゥイーン、「X を実行してから待ち、その後 Y を実行」など)。StartCoroutine で開始し、確実に停止します。
  6. Play モードで確認します。Console で null 参照例外がないか確認し、インスペクターの値が想定どおり更新されることを確認します。Update の負荷が高い場合は Profiler も確認します。
  7. 作業を終える前に .meta ファイルを確認します。 エディター外でスクリプトやアセットを作成、移動、名前変更、削除する場合は、必ずファイルと .meta を一緒に移動します(新しい .meta は新しい GUID を意味し、参照が壊れます)。次に python scripts/check_unity_project.py <project-dir> を実行し(機械可読形式の出力には --json を指定)、すべての ERROR(GUID の重複や形式不正、.meta を伴わないファイル移動、スクリプト参照の欠落)を修正して、終了コードが 0 になるまで再実行します。新規ファイルに .meta がない場合は警告にとどまり、次回のインポート時に Unity が作成します。スクリプトのパスはこのスキルディレクトリを基準にするか、先にインストール済みのスキルパスを解決してください。このスクリプトには Python 3.10 以降のみが必要で、それ以外の依存関係はありません。テキスト形式でシリアライズされたアセットのみを読み取り、Unity でプロジェクトを開く作業の代わりにはなりません。

パターン

1. ライフサイクルとコンポーネントのキャッシュ(基本のひな形)
using UnityEngine;

[RequireComponent(typeof(Rigidbody))]      // auto-adds the dependency, prevents null refs
public class PlayerController : MonoBehaviour
{
    [SerializeField] private float moveSpeed = 6f;   // editable in Inspector, private in code
    private Rigidbody _rb;                            // cached, not fetched per frame

    private void Awake() => _rb = GetComponent<Rigidbody>();  // cache once on load

    private void Update()
    {
        // Per-frame, non-physics work. Scale by deltaTime so it is frame-rate independent.
        transform.Rotate(0f, 90f * Time.deltaTime, 0f);
    }

    private void FixedUpdate()
    {
        // Physics work belongs here (fixed timestep). See the unity-physics skill.
        _rb.MovePosition(_rb.position + transform.forward * moveSpeed * Time.fixedDeltaTime);
    }
}
2. TryGetComponent による安全なコンポーネントアクセス
// Avoids allocating a null and is clearer than GetComponent + null check.
if (other.TryGetComponent<Health>(out var health))
    health.Apply(-10);
3. インスペクターに正しく表示されるシリアライズ
[SerializeField, Range(0f, 1f)] private float volume = 0.8f;  // slider
[SerializeField] private string playerName = "Hero";          // private but serialized

[System.Serializable]                 // REQUIRED for a plain class to serialize/show
public class Stats { public int hp = 100; public int mana = 50; }

[SerializeField] private Stats stats = new();  // nested struct-like data in the Inspector
4. 時間順に実行するロジックのためのコルーチン
private void Start() => StartCoroutine(FlashThenHide());

private System.Collections.IEnumerator FlashThenHide()
{
    yield return new WaitForSeconds(0.5f);   // wait half a second of game time
    GetComponent<Renderer>().enabled = false;
    yield return null;                       // resume next frame
}

注意点

  • Update 内でのGetComponent — フレームごとに検索するため、パフォーマンスが大幅に低下します。参照はAwake/Startでキャッシュしてください。
  • Update内での物理演算 — FixedUpdate以外で力やMovePositionを使ってRigidbodyを動かすと、動きが不安定になり、タイムステップに依存した挙動になります。入力はUpdateで読み取り、物理演算はFixedUpdateで適用してください。
  • オブジェクト間のStartの実行順に依存すること — StartはすべてのAwakeの後に実行されますが、Start同士の順序は未定義です。オブジェクト間の接続はStartで、自身のセットアップはAwakeで行ってください。
  • Inspectorに表示するためだけにフィールドをpublicにすること — そうすると、ほかのスクリプトからも変更できてしまいます。代わりに[SerializeField] privateを使用してください。
  • **gameObject.tag == "Enemy"**は文字列を割り当てるため処理が遅くなります。gameObject.CompareTag("Enemy")を使用してください。
  • GameObjectを無効にするとコルーチンが停止します — 無効化されたオブジェクトのコルーチンは終了します。切り替え後も継続させる必要がある場合は、OnEnableで再度StartCoroutineを呼び出してください。
  • UpdateがStartより前に実行されることはありませんが、最初のUpdateはStartと同じフレームで実行される場合があります — セットアップを不自然に分割している場合は、まだ初期化されていないフィールドへのアクセスを防いでください。

参考資料

  • イベント実行順序の一覧表や高度なコルーチンのパターン(カスタムのCustomYieldInstruction、ハンドルによる停止、WaitUntil/WaitWhile)については、references/lifecycle-and-coroutines.mdを参照してください。
  • scripts/check_unity_project.py — 読み取り専用の.meta/GUIDおよびスクリプト欠落チェッカーです。--helpですべてのチェック項目と終了コードを確認できます。
  • 主要ドキュメント:Unity Manualの「Event function execution order」(https://docs.unity3d.com/Manual/execution-order.html)およびScriptReference/MonoBehaviour。

関連スキル

  • unity-physics — Rigidbody、衝突、FixedUpdateでの移動。
  • unity-input-system — これらのスクリプトにプレイヤー入力を読み込む方法。
  • unity-scriptableobjects — シングルトンを使わずにスクリプト間でデータや設定を共有する方法。

コメント