mcpField
U
unity-csharp

unity-csharp

github.com/alexanderstephenthompson開発70 回インストール
リポジトリ

unity-csharp について

unity-csharp は、VR やモバイルを含む Unity の C# コードを書く開発者向けのスキルです。コンポーネントやライフサイクルのパターンに加え、プロファイリングと最適化の指針を扱います。

主な機能

  1. 01MonoBehaviour のライフサイクルとコンポーネント設計
  2. 02キャッシュ、イベント、コルーチン、null 安全性
  3. 03ScriptableObject によるデータ設計
  4. 04ドローコール、バッチング、LOD の最適化
  5. 05VR とモバイル向けのプロファイリング指針

活用シーン

  1. 01役割を絞った Unity コンポーネントでスクリプトを構成
  2. 02コンポーネント検索や Update 処理の反復を削減
  3. 03VR またはモバイル向けの描画を最適化
  4. 04CPU、メモリ、ドローコールの問題を分析

インストール

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

$npx skills add https://github.com/alexanderstephenthompson/claude-hub --skill unity-csharp

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

assets/
component-checklist.md
vr-performance-limits.md
references/
lifecycle.md
profiling.md

詳細

Unity C# スキル

バージョン: 2.0 スタック: Unity、C#

クリーンでパフォーマンスに優れた Unity C# コードを書くためのパターンです。VR/モバイル向けの最適化も含みます。


対象範囲と境界

このスキルの対象:

  • MonoBehaviour のライフサイクルとコンポーネントアーキテクチャ
  • Unity 固有の C# パターン(キャッシュ、イベント、コルーチン、null 安全性)
  • パフォーマンス最適化(ドローコール、バッチング、LOD、プーリング)
  • VR/モバイルのパフォーマンス目標とプロファイリング
  • ScriptableObject の使用

他のスキルに委ねる内容:

  • vrc-udon:VRChat 固有のスクリプティング(UdonSharp)
  • vrc-worlds:VRChat ワールドの設定と制限
  • vrc-avatars:VRChat アバターの設定と制限

このスキルを使用する場面: Unity 用の C# スクリプトを書く場合、または VR/モバイル向けに Unity のパフォーマンスを最適化する場合です。


基本原則

  1. 継承よりコンポジション — 小さく、目的を絞ったコンポーネントにします。
  2. 可能な限り Update() を避ける — 代わりにイベント駆動またはコルーチンを使います。
  3. 参照をキャッシュする — GetComponent はコストが高いため、Awake でキャッシュします。
  4. データには ScriptableObject を使う — データと動作を分離します。
  5. null 安全なアクセス — Unity オブジェクトはいつでも破棄される可能性があります。
  6. まず計測する — 最適化の前にプロファイリングします。勘は当てになりません。
  7. 積極的にバッチ化する — 同じマテリアルならバッチ化できる可能性があります。VR ではドローコールが最も重要です。

パターン

参照のキャッシュ
public class PlayerController : MonoBehaviour
{
    private Rigidbody _rb;
    private Animator _animator;

    [SerializeField] private Transform _cameraTarget;

    private void Awake()
    {
        _rb = GetComponent<Rigidbody>();
        _animator = GetComponent<Animator>();
    }

    private void FixedUpdate()
    {
        _rb.AddForce(Vector3.up);
    }
}
イベントシステム(ScriptableObject)
[CreateAssetMenu(menuName = "Events/Game Event")]
public class GameEvent : ScriptableObject
{
    private readonly List<GameEventListener> _listeners = new();

    public void Raise()
    {
        for (int i = _listeners.Count - 1; i >= 0; i--)
            _listeners[i].OnEventRaised();
    }

    public void RegisterListener(GameEventListener listener) =>
        _listeners.Add(listener);

    public void UnregisterListener(GameEventListener listener) =>
        _listeners.Remove(listener);
}

public class GameEventListener : MonoBehaviour
{
    [SerializeField] private GameEvent _event;
    [SerializeField] private UnityEvent _response;

    private void OnEnable() => _event.RegisterListener(this);
    private void OnDisable() => _event.UnregisterListener(this);
    public void OnEventRaised() => _response.Invoke();
}
null 安全なパターン
// Unity overloads == for destroyed objects
if (_target != null)
{
    _target.DoSomething();
}

// Best: explicit destroyed check
if (_target != null && !_target.Equals(null))
{
    _target.DoSomething();
}
コルーチンのパターン
private IEnumerator FadeOut(float duration)
{
    float elapsed = 0f;
    Color startColor = _renderer.material.color;

    while (elapsed < duration)
    {
        elapsed += Time.deltaTime;
        float t = elapsed / duration;
        _renderer.material.color = Color.Lerp(startColor, Color.clear, t);
        yield return null;
    }

    gameObject.SetActive(false);
}
オブジェクトプーリング
public class ObjectPool : MonoBehaviour
{
    [SerializeField] private GameObject _prefab;
    [SerializeField] private int _initialSize = 10;

    private Queue<GameObject> _pool = new();

    private void Awake()
    {
        for (int i = 0; i < _initialSize; i++)
        {
            var obj = Instantiate(_prefab);
            obj.SetActive(false);
            _pool.Enqueue(obj);
        }
    }

    public GameObject Get()
    {
        if (_pool.Count == 0)
            return Instantiate(_prefab);

        var pooled = _pool.Dequeue();
        pooled.SetActive(true);
        return pooled;
    }

    public void Return(GameObject obj)
    {
        obj.SetActive(false);
        _pool.Enqueue(obj);
    }
}
静的バッチング
gameObject.isStatic = true;

// Or specific flags
GameObjectUtility.SetStaticEditorFlags(gameObject,
    StaticEditorFlags.BatchingStatic |
    StaticEditorFlags.OcclusionStatic);

VR のパフォーマンス目標

指標Quest 2Quest 3PC VR
ドローコール<100<150<200
三角形数<100K<150K<1M
フレーム時間<14ms (72fps)<11ms (90fps)<11ms (90fps)
テクスチャメモリ<200MB<500MB<1GB
LOD の設定
LOD 0: 100% triangles (0-10m)
LOD 1: 50% triangles (10-25m)
LOD 2: 25% triangles (25-50m)
Culled: 0 triangles (50m+)
マテリアルアトラス化
Before: 20 objects x 20 materials = 20 draw calls (no batching)
After:  20 objects x 1 atlas material = 1 draw call (batched)

アンチパターン

アンチパターン問題対処法
Update 内での GetComponentフレームごとにコストがかかるAwake でキャッシュする
Find または FindObjectOfType遅く、壊れやすい参照を注入するか、イベントを使う
負荷の高い Update ループパフォーマンスを低下させるイベント、コルーチン、または FixedUpdate を使う
タグの文字列比較タイプミスが起きやすく、遅いCompareTag または定数を使う
すべてを public フィールドにするカプセル化されない[SerializeField] private を使う
オブジェクトごとに異なるマテリアルバッチ化できないマテリアルを共有し、アトラスを使う
LOD がない距離にかかわらず最高詳細度で表示されるLOD グループを追加する
ゲームプレイ中の Instantiate/DestroyGC スパイクやカクつきが発生するオブジェクトプーリングを使う
あらゆる場所でのリアルタイムライトシャドウのコストが高いライティングをベイクし、リアルタイムライトを制限する
オクルージョンカリングがない隠れたオブジェクトもレンダリングされるオクルージョンデータをベイクする

チェックリスト

コード品質
  • 参照を Awake でキャッシュしている
  • Update/FixedUpdate 内で GetComponent を使っていない
  • 実行時コードで Find 系のメソッドを使っていない
  • 共有データに ScriptableObject を使っている
  • 疎結合な通信にイベントを使っている
  • 破棄される可能性のあるオブジェクトに null チェックを行っている
パフォーマンス
  • 静的オブジェクトに static を設定している
  • 可能な範囲でマテリアルを共有している
  • 小さな小道具にテクスチャアトラスを使っている
  • 重要なメッシュに LOD グループを設定している
  • オクルージョンカリングをベイクしている
  • 生成されるオブジェクトにオブジェクトプーリングを使っている
  • ライティングをベイクしている(すべてをリアルタイムにしていない)
プロファイリング
  • Frame Debugger でドローコールを確認した
  • Profiler を実行して CPU スパイクを確認した
  • Memory Profiler でリークを確認した
  • 対象デバイスでテストした(エディターだけで済ませていない)

参考資料

  • references/lifecycle.md — MonoBehaviour のライフサイクルと実行順序
  • references/profiling.md — Unity Profiler の使用方法と結果の解釈

アセット

  • assets/component-checklist.md — Unity コンポーネント設計チェックリスト
  • assets/vr-performance-limits.md — VR プラットフォームのパフォーマンス制限と目標

コメント