Unity について
Unity ゲーム開発者向けのガイドで、プロジェクトの立ち上げからリリースまでを扱います。C# の実践パターンやアーキテクチャ、性能改善の指針を、分野別の参考資料とともにまとめています。
主な機能
- 01プロジェクト構成とアセット規約
- 02C# と MonoBehaviour のパターン
- 03アーキテクチャとデザインパターン
- 04プロファイリングと性能改善
- 05ワークフロー、テスト、ビルドの実践
- 06Unity 6 と専門システム
活用シーン
- 01拡大する Unity プロジェクトの整理
- 02ゲームスクリプトの作成やレビュー
- 03性能問題の調査
- 04ゲームの設計方針やワークフローの選定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ juliankerignard/ unity-skills --skill unityインストール後、Claude Code で/unityを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/architecture-advanced.mdarchitecture.mdworkflow.mdperformance.mdcsharp-patterns.mdsystems.mdspecialized.mdproject-structure.md詳細
Unity 開発ガイド
プロジェクトのセットアップからリリースまで、実戦で培われた Unity のベストプラクティスを紹介します。ここが入口です。詳しい内容については、各リファレンスファイルをご覧ください。
リファレンスファイル — 内容に応じた参照先
| 作業内容… | 参照先 |
|---|---|
| フォルダーの整理、アセットの命名、インポート設定 | references/project-structure.md |
| C# スクリプトの作成やレビュー | references/csharp-patterns.md |
| パフォーマンス問題の調査や最適化 | references/performance.md |
| ゲームアーキテクチャ、パターン、システムの設計 | references/architecture.md |
| Git、テスト、CI/CD、ビルドの設定 | references/workflow.md |
| アニメーション、2D、Shader/VFX Graph | references/specialized.md |
| デバッグ、ローカライズ、アクセシビリティ、AI/Inference Engine | references/systems.md |
| UI Toolkit や Cinemachine のセットアップ | references/architecture-advanced.md |
コードを書く前に、関連するリファレンスを確認してください。そこに記載されたパターンを活用すれば、大幅な手戻りを防げます。
1. プロジェクト構成
機能ごとにフォルダーを分ける方法は、型ごとに分ける方法よりも、プロジェクトの成長に合わせて拡張しやすくなります。関連するコードをまとめておけるためです。
Assets/
├── _Project/
│ ├── Scripts/
│ │ ├── Core/ # Game loop, managers, bootstrap
│ │ ├── Player/ # Controller, input, camera
│ │ ├── Enemies/ # AI, spawners, enemy types
│ │ ├── UI/ # Views, presenters, screens
│ │ ├── Data/ # ScriptableObject definitions
│ │ └── Utils/ # Extensions, helpers
│ ├── Prefabs/
│ ├── Scenes/
│ ├── ScriptableObjects/ # Data asset instances
│ ├── Art/ # Models, Textures, Materials, Animations, Shaders
│ └── Audio/ # SFX, Music
├── Plugins/ # Third-party SDKs
└── Settings/ # Render pipeline, input, quality
なぜ _Project/ を使うのでしょうか? アンダースコアを先頭に付けると、Assets フォルダーの最上部に配置され、コードをインポートしたパッケージやサードパーティ製アセットから分離できます。
なぜ Resources/ を使わないのでしょうか? Unity は起動時に Resources/ 内のすべてをメモリに読み込みます。少数の小さなアセットを超える場合は、代わりに Addressables システムを使いましょう。必要に応じて読み込み、リモートコンテンツの配信にも対応しています。
フォルダー構成、アセットの命名規則、インポート設定、プレハブやシーンの規則、ゲームジャムから大規模プロジェクトへ拡張する方法について詳しくは、references/project-structure.md をご覧ください。
アセンブリ定義
コードをアセンブリ(.asmdef)に分割することは、反復速度を高めるうえで最も効果の大きい取り組みの一つです。分割しない場合、どのスクリプトを変更してもすべてが再コンパイルされます。分割すると、Unity は影響を受けるアセンブリのみを再コンパイルします。
Scripts/Core/ → Game.Core.asmdef
Scripts/Player/ → Game.Player.asmdef (refs: Game.Core)
Scripts/UI/ → Game.UI.asmdef (refs: Game.Core)
Scripts/Utils/ → Game.Utils.asmdef (no dependencies)
命名規則
| 要素 | 規則 | 例 |
|---|---|---|
| クラス/構造体 | PascalCase | PlayerController |
| パブリックメソッド | PascalCase | TakeDamage() |
| プライベートフィールド | _camelCase | _currentHealth |
| シリアライズ対象のフィールド | [SerializeField] + _camelCase | [SerializeField] private float _speed; |
| インターフェース | I を接頭辞に付ける | IDamageable |
| ScriptableObjects | SO を接尾辞に付ける | WeaponDataSO |
| 列挙型 | PascalCase、単数形 | WeaponType { Sword, Bow } |
2. C# の基本パターン
これらは、ほぼすべての Unity プロジェクトで使われるパターンです。全項目(ライフサイクルの順序、非同期パターン、拡張機能、エディタースクリプティング)について詳しくは、references/csharp-patterns.md をご覧ください。
整理された MonoBehaviour
適切に構成された MonoBehaviour では、シリアライズ対象の設定を先頭に置き、その後にイベント、プライベートな状態、ライフサイクルメソッドの順に並べます。この構成により、クラスの内容をひと目で把握しやすくなります。
public class PlayerHealth : MonoBehaviour, IDamageable
{
[Header("Config")]
[SerializeField] private int _maxHealth = 100;
[SerializeField] private float _invincibilityTime = 0.5f;
[Header("Refs")]
[SerializeField] private HealthBarUI _healthBar;
public event Action<int, int> OnHealthChanged; // current, max
public event Action OnDeath;
private int _currentHealth;
private bool _isInvincible;
private void Awake() => _currentHealth = _maxHealth;
private void Start() => _healthBar?.SetMaxHealth(_maxHealth);
public void TakeDamage(int damage)
{
if (_isInvincible || _currentHealth <= 0) return;
_currentHealth = Mathf.Max(0, _currentHealth - damage);
OnHealthChanged?.Invoke(_currentHealth, _maxHealth);
if (_currentHealth <= 0) { OnDeath?.Invoke(); return; }
StartCoroutine(InvincibilityCo());
}
private IEnumerator InvincibilityCo()
{
_isInvincible = true;
yield return new WaitForSeconds(_invincibilityTime);
_isInvincible = false;
}
}
主要な原則
[SerializeField] private を public フィールドより優先します。 public フィールドはカプセル化を損ない、ほかのスクリプトから自由に書き換えられるため、バグの原因を追跡しにくくなります。[SerializeField] を使うと、フィールドを Inspector に表示しながら、ほかのコードからは private に保てます。
コンポーネントごとに責務をひとつにします。 ひとつの巨大な Player ではなく、PlayerMovement、PlayerHealth、PlayerCombat に分けます。これにより、ほかのシステムに影響を与えるリスクを抑えながら、ひとつのシステムだけを改善でき、コンポーネントも再利用しやすくなります。
参照は Awake() でキャッシュします。 GetComponent、Find、FindObjectOfType はすべて検索処理です。実行時、特に Update 内で呼び出すと、CPU サイクルを無駄に消費します。初期化時に一度だけキャッシュしてください。
GetComponent<T>() より TryGetComponent<T>() を優先します。 bool を返し、null 参照例外を防げるうえ、わずかに高速です。
直接結合させず、イベントで通信します。 システム A からシステム B に何かが起きたことを伝える場合は、C# イベントまたは ScriptableObject のイベントチャネルを使います。これによりシステムが独立し、テストしやすくなります。
ScriptableObject アーキテクチャ
ScriptableObject(SO)は、プロジェクト内に保存され、シーンをまたいで保持されるアセットです。適切に疎結合された Unity プロジェクトの基盤となります。
データコンテナ — 武器のステータス、敵の設定、レベル設定:
[CreateAssetMenu(menuName = "Game/Weapon Data")]
public class WeaponDataSO : ScriptableObject
{
public string weaponName;
[Range(1, 100)] public int damage = 10;
[Range(0.1f, 5f)] public float attackSpeed = 1f;
public AudioClip[] attackSounds;
}
イベントチャネル — システム間の完全に疎結合なパブリッシュ/サブスクライブ:
[CreateAssetMenu(menuName = "Events/Void Event")]
public class VoidEventChannelSO : ScriptableObject
{
private Action _onRaised;
public void Raise() => _onRaised?.Invoke();
public void Subscribe(Action fn) => _onRaised += fn;
public void Unsubscribe(Action fn) => _onRaised -= fn;
}
便利な点は、パブリッシャーが SO アセットの Raise() を呼び出すだけでよいことです。サブスクライバーは同じアセットを参照してリッスンします。互いの存在を知る必要はありません。Inspector 経由で接続します。ランタイムセットや共有変数など、パターン全般については references/architecture.md を参照してください。
3. パフォーマンス — 基本事項
パフォーマンスの問題は、CPU(フレームあたりのロジックが多すぎる)、GPU(レンダリング対象が多すぎる)、メモリ(アロケーションによる GC の一時停止)の 3 つに分類されます。最も重要なルールは、まずプロファイリングし、その後に最適化することです。推測する前に、Window > Analysis > Profiler を開いてください。
フレーム予算: 60fps では 16.6ms、30fps では 33.3ms です。予算を 1 ミリ秒でも超えると、フレーム落ちが発生します。
ホットパスでのアロケーションをゼロにする
ガベージコレクター(GC)が実行されると、ゲームは一時停止します。Update()、FixedUpdate()、その他のフレームごとに実行されるコード内でのアロケーションが、主な原因です。
// Problematic — allocates every frame
void Update() {
var enemies = FindObjectsOfType<Enemy>(); // array allocation
string s = "HP: " + _health; // string concat
var list = new List<int>(); // list allocation
}
// Better — pre-allocate, reuse
private readonly StringBuilder _sb = new();
private readonly List<int> _reusable = new();
void Update() {
_sb.Clear().Append("HP: ").Append(_health);
_reusable.Clear();
// ... fill _reusable as needed
}
オブジェクトプーリング
頻繁な Instantiate()/Destroy() は、GC のスパイクやメモリの断片化を引き起こします。代わりにオブジェクトをプールしてください。Unity 6 以降には UnityEngine.Pool.ObjectPool<T> が標準で用意されています。または、Queue<GameObject> を使って独自に作成できます。
レンダリングですぐにできる改善
- 動かないオブジェクトには Static Batching を使用します(Inspector で「Static」をオンにします)
- 繰り返し使うメッシュには GPU Instancing を使用します(Material で有効にします)
- 複雑な 3D モデルには LOD Groups を使用します
- 可能な場合は Baked lighting を使用します。リアルタイムライトは、特にモバイルでは高負荷です
- 屋内や複雑なシーンでは Occlusion Culling を使用します
物理演算、モバイル向けの目標、テクスチャの予算、プロファイリングのワークフロー、Jobs/Burst を含むパフォーマンスの完全なガイドについては、references/performance.md を参照してください。
4. アーキテクチャの判断
プロジェクト規模に応じて選ぶ
| 規模 | チーム | 推奨するアプローチ |
|---|---|---|
| ゲームジャム/プロトタイプ | 1-2 | シングルトン + 直接参照 |
| 小規模インディー | 1-3 | ScriptableObject アーキテクチャ |
| 中規模 | 3-10 | SO アーキテクチャ + サービスロケーター |
| 大規模/ライブサービス | 10+ | DI フレームワーク(VContainer)+ 必要に応じて ECS |
プロジェクトの規模に対して過剰な設計は避けてください。ゲームジャムに依存性注入は不要です。2 年間運用するライブサービスゲームには必要です。
主なパターンのまとめ
| パターン | 用途 |
|---|---|
| SO イベントチャネル | シーンをまたぐ疎結合な通信 |
| ステートマシン | プレイヤーの状態、AI、ゲーム進行、UI 画面 |
| サービスロケーター | シングルトンを使わないグローバルなシステムアクセス |
| コマンド | 入力処理、元に戻す/やり直し、リプレイ |
| MVP(Model-View-Presenter) | UI システム |
| オブジェクトプール | 頻繁に生成/破棄されるオブジェクト |
各パターンの完全な実装については、references/architecture.md を参照してください。
5. モダンな Unity(Unity 6+)
Unity 6 は現行世代です。最新の LTS は Unity 6.3(2025 年 12 月)で、新規プロジェクトの推奨ベースラインです。Unity は四半期ごとにアップデートされます(6.1 → 6.2 → 6.3 LTS → 6.4+)。
パイプラインの選択
特定の HDRP 機能(レイトレーシング、ボリューメトリックフォグ、ハイエンドコンソール向けの高精細な描画)が必要でなければ、URP から始めましょう。URP はモバイル、VR、2D、ミドルレンジの PC に対応します。Unity は URP と HDRP をつなぐ 統合レンダラー(共有の Render Graph バックエンド)への移行を進めていますが、現時点ではプロジェクトの途中でパイプラインを切り替えるのは依然として困難です。早い段階で決めてください。
Addressables
本番環境では Resources.Load() を置き換えましょう。Addressables はアセットを必要に応じて読み込み、非同期読み込みに対応し、リモートコンテンツの配信を可能にします。覚えておくべき重要な点は、使い終わったら必ずハンドルを解放することです。そうしないとメモリリークが発生します。
New Input System
複数のプラットフォームや入力デバイスを対象とするプロジェクトでは、新しい Input System パッケージを使用しましょう。単一の抽象化レイヤー(Input Actions アセット)を通じて、キーボード、ゲームパッド、タッチ、XR の入力を処理します。
Unity 6 の API 変更
明確さを高めるため、いくつかの API の名前が変更されました。
Rigidbody.velocity→Rigidbody.linearVelocity(Rigidbody2D も同様)Rigidbody.angularVelocityは引き続き使用できますが、非推奨の警告を確認してください- Cinemachine 2.x → Cinemachine 3.x(
CinemachineVirtualCamera→CinemachineCamera。コンポーネント名が大幅に変更されています。architecture.md §10 を参照してください)
Unity 6.3 LTS の主な機能
- Box2D v3 低レベル 2D 物理 API(マルチスレッド、決定論的、ビジュアルデバッグ対応)— 既存の API と並行して動作し、将来的には置き換える予定です
- Platform Toolkit — PS5/Xbox/Switch/Steam/Android/iOS 間でアカウント、実績、セーブデータを扱う統合 API
- Mesh LOD — 静的メッシュとスキンドメッシュの LOD をエディター内で自動生成
- Shader Graph — 地形シェーダーのサポート、8 つのテクスチャ座標セット、テンプレートブラウザー
- Scriptable Audio Pipeline — Burst コンパイルされた C# プロセッサーでオーディオチェーンを拡張
- UI Toolkit にカスタムシェーダー、フィルター、SVG(コアモジュールになりました)、ワールド空間のサポート強化が追加されます
- 2D Renderer は、2D URP でスプライトとともに Mesh Renderer および Skinned Mesh Renderer をレンダリングできるようになりました
- Sprite Atlas Analyser ツールでパッキングの非効率な箇所を特定
DOTS / ECS
ECS は、処理対象となる類似エンティティが数千個ある場合(大規模シミュレーション、群衆 AI、サーバーサイドのマルチプレイヤー)に威力を発揮します。アクティブなエンティティが数百個未満の大半のインディーおよび中規模プロジェクトでは、従来の MonoBehaviour アプローチの方がシンプルで十分です。DOTS を使用する場合は、Unity.Mathematics の型を使い、構造変更には EntityCommandBuffer を使用し、ECS(ロジック)と GameObjects(オーサリング/レンダリング)を組み合わせましょう。Unity のロードマップには、将来のバージョンで ECS の統合をさらに深める計画が含まれています。
Netcode for GameObjects
マルチプレイヤーでは、最初からサーバーオーソリタティブな設計を考えましょう。すべての入力をサーバーで検証し、同期状態には NetworkVariable<T> を使用し、応答性を高めるためにクライアント側予測を適用します。差分のみを同期して帯域幅を最小限に抑えましょう。
6. よくあるアンチパターン
| アンチパターン | 問題点 | より良い方法 |
|---|---|---|
巨大な GameManager クラス | 保守が困難になり、あらゆる要素が密結合になります | 責務ごとにシステムを分割します |
Update 内での Find*() | 毎フレーム、線形検索が発生します | Awake でキャッシュし、イベントを使います |
| あらゆるフィールドを public にする | カプセル化できず、バグの追跡が困難になります | [SerializeField] private |
| 文字列によるアニメーションパラメーター | タイプミスが気づきにくい失敗を引き起こします | Animator.StringToHash() でキャッシュします |
| 深い継承 | 柔軟性に欠け、リファクタリングが困難になります | コンポジションとインターフェース |
| ハードコードされたマジックナンバー | 再コンパイルしないと調整できません | ScriptableObjects または const |
7. クイック判断ガイド
| 判断項目 | デフォルトの選択肢 | 次の場合は別の選択肢を検討してください… |
|---|---|---|
| レンダリングパイプライン | URP | レイトレーシングやボリューメトリックフォグが必要な場合 → HDRP |
| アセットの読み込み | Addressables | アセットが 20 個未満の小規模プロジェクトの場合 → Resources |
| 入力 | New Input System | エディター専用ツールで、ゲームパッドが不要な場合 → old Input |
| 非同期処理 | Awaitable (Unity 6+) | Unity 6 より前のバージョンの場合 → UniTask または Coroutines |
| マルチプレイヤー | Netcode for GameObjects | MMO/大規模な場合 → 専用サーバー + ECS |
| UI(メニュー、HUD) | UI Toolkit | ゲーム内 UI またはレガシープロジェクトの場合 → uGUI Canvas |
| カメラ | Cinemachine | 非常にシンプルな固定カメラの場合 → 手動スクリプト |
| 物理演算 | 組み込みの 3D/2D Physics | 1 万個以上の剛体を扱う場合 → DOTS Physics |
| パーティクル(100 個未満) | Shuriken (Particle System) | 1000 個以上のパーティクルまたは GPU エフェクトの場合 → VFX Graph |
| パーティクル(1000 個以上) | VFX Graph | コンピュートシェーダー非対応のモバイルの場合 → Shuriken |
| ローカライズ | Unity Localization package | ごく小規模なゲームジャムプロジェクトの場合 → 文字列をハードコード |
| バージョン管理 | Git + LFS | 大規模チームまたはバイナリファイルが多い場合 → Perforce / Plastic |
| アニメーションのブレンド | Blend Trees | ブレンドなしの離散状態の場合 → シンプルな遷移 |
| 2D 物理演算 | 組み込みの Physics2D | 高パフォーマンス/決定論が必要な場合 → Box2D v3 low-level API (6.3+) |
| クロスプラットフォームサービス | Platform Toolkit (6.3+) | 古い Unity の場合 → プラットフォームごとの SDK を手動で導入 |
関連スキル
| ニーズ | スキル |
|---|---|
| 本番環境向け C# コードの生成 | /unity-code-gen (Unity Code Gen) |
| コードのテスト | /unity-test (Unity Test) |
| 問題のデバッグ | /unity-debug (Unity Debug) |
| すばやいプロトタイプ作成 | /proto (Unity Rapid Proto) |
| パフォーマンス監査 | /perf-audit (Unity Perf Audit) |
| 既存コードのリファクタリング | /unity-refactor (Unity Refactor) |
| カスタムエディターツール | /editor (Unity Editor Tools) |
| HLSL シェーダー | /shader (Unity Shader Generator) |
| UI Toolkit を使った UI | /uitk (Unity UI Toolkit) |
| NGO マルチプレイヤー | /netcode (Unity Multiplayer) |
| 非同期アセット読み込み | /addressables (Unity Addressables) |
| 高度なアニメーション | /anim (Unity Animation) |
| ECS と Jobs | /dots (Unity DOTS) |
| ビルドと CI/CD | /build-config (Unity Build & CI/CD) |
| オーディオシステム | /unity-audio (Unity Audio) |
| 2D 開発 | /2d (Unity 2D) |
| セーブと永続化 | /unity-save (Unity Save System) |