unity-scriptdesign について
ゲームプレイコードを作成・改善する Unity 開発者向けの設計レビュー用スキルです。責務や結合度、性能、保守性に加え、状態のライフサイクル上の配置も確認します。
主な機能
- 01スクリプトの責務とクラスの役割を確認
- 02依存関係、通信、結合度を評価
- 03状態をデータのライフサイクル別に整理
- 04実際の性能上の問題点を指摘
- 05所定の形式でレビュー結果を提示
活用シーン
- 01ゲームプレイスクリプト作成前の設計評価
- 02密結合したスクリプトの整理
- 03保守性を高めるリファクタリングの計画
- 04生成スクリプトの性能とライフサイクルの確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ besty0728/ unity-skills --skill unity-scriptdesignインストール後、Claude Code で/unity-scriptdesignを入力して読み込まれたか確認します。
詳細
このモジュールのスキルを呼び出す前に: スキル名や説明から推測したパラメーターでスキルを呼び出そうとしている場合は、いったん停止し、まずこのファイルを読むか、
GET /skills/recommend?includeSchema=trueでスキーマを取得してください。recommend/schema からパラメーターの定義をすでに取得している場合は、そのまま dryRun に進んでかまいません。
トリガー
- コード品質のレビュー
- 密結合したスクリプトの整理
- 保守性を高めるためのリファクタリング計画
- コード品質のレビュー、密結合したスクリプトの整理、保守性を高めるためのリファクタリング計画
Unity スクリプト設計レビュー
ゲームプレイ用スクリプトを作成する前、または生成されたスクリプトの設計を見直す必要があるときに、このスキルを使用してください。
レビューチェックリスト
- 責務:スクリプトの役割は明確に一つに定まっていますか?
- 役割:本当に
MonoBehaviour、ScriptableObject、または通常の C# クラスにすべきですか? - 結合度:隠れたグローバル変数や深いシーン検索に頼らず、依存関係が明示されていますか?
- 通信:直接参照、インターフェイス呼び出し、イベントのどれを使うべきですか?
- パフォーマンス:不要な
Update、繰り返しのFind、回避可能なメモリ割り当て、または頻繁に実行される処理内のリフレクションはありませんか? - ライフサイクル:購読、タイマー、非同期処理が明確にクリーンアップされていますか?
- インスペクターの使いやすさ:シリアライズ対象のフィールドは private で、グループ化され、説明が付いていますか?
- テスト容易性:中核となるロジックを通常の C# クラスに切り出せますか?
- 命名:クラス名とフィールド名から、分かりにくい略語を使わずに意図が伝わりますか?
データのライフサイクル境界
上のレビューチェックリストでは、「このクラスはどこに置くべきか」を尋ねています。すべてのフィールドについても同じ問いを立ててください。状態には3種類のライフサイクルがあり、フィールドを誤ったライフサイクルに置くことが、「デザイナーが値を変更したらなぜ壊れたのか」「なぜユニットテストが不安定なのか」という問題の最も一般的な原因です。
| ライフサイクル | 値が決まるタイミング | 配置場所 | 典型的な書き方 |
|---|---|---|---|
| 作成時 | Play の前に、デザイナーが Editor で決定 | ScriptableObject アセット、またはプレハブ上の [SerializeField] private | 実行時は不変。_config.Speed 経由で読み取る |
| 構成時 | シーン/インスタンスごとに1回、Awake/Start 時 | private フィールド。GetComponent/GetComponentInChildren/コンストラクター引数から代入 | 参照をキャッシュし、フレームごとの検索は行わない |
| 実行時に変更可能 | 毎フレーム、またはゲームプレイイベント発生時 | private バッキングフィールド+読み取り専用の public プロパティ+イベント | public float Health { get; private set; } + OnHealthChanged で公開 |
典型的な割り当て
- 武器のダメージ/連射速度/マガジン容量 → 作成時(バランス調整のため、ホットスワップできるよう ScriptableObject を使用)。
- 敵 AI の現在のターゲット
Transform→ スポーン時に一度だけ設定する場合は 構成時、毎フレームターゲットを切り替える場合は 実行時に変更可能。 - プレイヤーの現在の HP → イベントを伴う 実行時に変更可能。
public float hp;は決して使用しないでください。 - 同じ GameObject 上の
Rigidbody/Animatorへの参照 → 構成時にAwakeでキャッシュ。 - レベルの音楽トラック → ScriptableObject のレベル記述子を使って 作成時に設定。
- 「戦闘中かどうか」のフラグ → 実行時に変更可能ですが、通常は他の状態から導出されます。そもそもフィールドにすべきか見直してください。
分離が重要な理由
3種類のライフサイクルを混在させると、クラスは適切に整理された状態からゴッドオブジェクトへと変わります。public float speed を持つ MonoBehaviour が、インスペクターとパワーアップスクリプトの両方から編集されると、値の所有者が2つになり、不変条件がなくなります。どちらの経路で発生したバグも、もう一方に影響します。ECS のベーキングパイプラインでは、この区別が(Authoring → Baker → System)という厳格なアーキテクチャ境界になっており、その原則はそのまま適用できます。ECS で Authoring コンポーネントと実行時の書き戻しを混在させないのであれば、MonoBehaviour でも混在させないでください。出典:EntitiesSamples/Docs/baking.md:5-16。
ガードレール
モード:ドキュメントのみ — ゲート対象となる REST スキルはありません。承認/自動/バイパスのいずれの動作モードでも自由に読み込めます。
- ローカルな略称より、説明的な名前を優先してください。
- 想定上の生産性向上のために、読みやすさを損なう「最適化」はしないでください。
- 小規模なリファクタリングで本当の問題を解決できる場合は、複雑なパターンを勧めないでください。
出力形式
- 維持する点:すでに良い点
- 簡素化する点:シンプルなままにすべき点
- リファクタリング:最も価値の高い構造上の変更
- パフォーマンスに関する注記:理論上のマイクロ最適化ではなく、実際のボトルネックのみ
- 保守性に関する注記:命名、所有権、結合度、エディターでの使いやすさ