学習記事一覧 · Unity

IkinokoBattle で学ぶ Unity OOP 設計パターン:目次

このシリーズは、技術評論社刊『作って学べる Unity本格入門[Unity 6対応版]』(賀好 昭仁 著)の題材プロジェクト IkinokoBattle のソースコードを題材に、オブジェクト指向設計(OOP)のパターンを読み解きます。
本サイトは出版社・著者の公式サイトではありません。 コード掲載は学習上必要な範囲にとどめます。
実装編(Chapter 5〜9) | 機能別解説編


書籍・著作について

  • 出典: 技術評論社刊『作って学べる Unity本格入門[Unity 6対応版]』(賀好 昭仁 著)
  • 本ブログの位置づけ: 題材プロジェクトのコードを読み解く学習補助の解説です。書籍の代替提供を目的とせず、**コード掲載は学習上必要な範囲(必要最小限)**にとどめます。
  • 著作権・サンプルの利用: 書籍に関する権利は出版社・著者に帰属します。サンプル等の利用条件は書籍記載(P.4〜5)および出版社サポート情報に従ってください。

このシリーズについて

  • 対象読者: C# と Unity の基礎を習得し、「なぜこう書くのか」を深く理解したい方
  • 記事の構成: OOP 設計パターンを 1 パターン(または関連する 2 パターン)ずつ取り上げ、IkinokoBattle の実装コードと照らし合わせながら解説します
  • シリーズの目的: デザインパターンの「名前と定義を知る」だけでなく、Unity の MonoBehaviour や ScriptableObject、UnityEvent といった仕組みの中でどう活かすかを体感することにあります

記事一覧


第1回|シングルトンパターン

記事ファイル: 01-OOP_シングルトンパターン.md

アプリケーション全体で「唯一のインスタンス」を保証する Singleton パターンを、IkinokoBattle の 3 つのバリエーションで読み解きます。

登場クラス

クラス 種別 シングルトンの方式
OwnedItemsData 純粋 C# Lazy<T> による遅延初期化、private コンストラクタ
AudioManager MonoBehaviour DontDestroyOnLoad + 重複時 Destroy
LifeGaugeContainer MonoBehaviour 重複時に Exception をスロー(厳格版)

学習ポイント

# 学習ポイント
private コンストラクタで外部からの new を禁止する
Lazy<T> で初回アクセス時のみインスタンスを生成する
MonoBehaviour では DontDestroyOnLoad でシーンをまたいで存続させる
Awake で重複チェックし、既存インスタンスがあれば Destroy(gameObject) する
3 種のバリエーション(純 C#・MonoBehaviour 寛容版・MonoBehaviour 厳格版)を使い分ける

第2回|テンプレートメソッドパターンと抽象クラス

記事ファイル: 02-OOP_テンプレートメソッド.md

「処理の骨格を親クラスが定め、詳細を子クラスが埋める」Template Method パターンを、MobStatusPlayerStatus / EnemyStatus の継承ツリーで解説します。

登場クラス

クラス 役割
MobStatus(abstract) 共通の HP 管理・ダメージ処理・死亡判定の骨格
PlayerStatus OnDead() でゲームオーバーシーンへ遷移
EnemyStatus OnDead() で敵 GameObject を非アクティブ化

学習ポイント

# 学習ポイント
abstract classabstract メソッドで「必ず実装すべき処理」を強制する
virtual / override で「デフォルト実装を持ちつつ上書き可能」にする
protected フィールドで子クラスだけに公開する
骨格メソッド(Damage())の中で抽象メソッド(OnDead())を呼ぶ仕組みを読む
継承 vs 委譲の使い分け:「is-a 関係」が成立するときに継承を選ぶ判断基準

第3回|委譲パターンと UnityEvent

記事ファイル: 03-OOP_委譲とUnityEvent.md

「仕事を別のオブジェクトに委ねる」委譲(Delegation)パターンを、CollisionDetectorUnityEvent<T> の組み合わせで解説します。継承に頼らず柔軟に振る舞いを差し込む手法を学びます。

登場クラス

クラス 役割
CollisionDetector トリガー判定を UnityEvent<Collider> に変換して委譲する汎用コンポーネント
EnemyMove CollisionDetector のイベントを受け取り、追跡処理を開始する
MobAttack 同じく CollisionDetector を利用して攻撃範囲判定を委譲する

学習ポイント

# 学習ポイント
UnityEvent<T> でコールバックを型安全に定義する
[SerializeField] + Inspector でイベントリスナーを登録する方法とコードで登録する方法の違い
CollisionDetector を汎用化することで他のコンポーネントが OnTriggerEnter を直接持たなくて済む理由
委譲と継承の違い:「has-a 関係」で機能を組み合わせる
単一の GameObject に複数の CollisionDetector をアタッチして用途別に分ける設計

第4回|単一責任の原則とコンポーネント設計

記事ファイル: 04-OOP_単一責任.md

「クラスの変更理由は 1 つだけ」という Single Responsibility Principle(SRP)を、PlayerController[RequireComponent] の仕組みで読み解きます。MonoBehaviour を小さく保つ設計思想を学びます。

登場クラス

クラス 担当責任
PlayerController 入力受付・移動・アニメーション指示の調整役
CharacterController 物理移動・衝突判定(Unity 組み込み)
PlayerInput Input System との橋渡し(Unity 組み込み)
PlayerStatus HP 管理・ダメージ受付
LifeGauge HP の UI 表示

学習ポイント

# 学習ポイント
[RequireComponent(typeof(T))] でコードで依存関係を宣言する
GetComponent<T>()Awake でキャッシュしてパフォーマンスを保つ
「入力」「移動」「HP」「UI」を別クラスに分ける理由とメリット
PlayerController が他クラスのメソッドを「呼ぶだけ」になる調整役パターン
SRP 違反の例:1 クラスに何でも詰め込んだときの変更コストを考える

第5回|状態パターン(State Pattern)

記事ファイル: 05-OOP_状態パターン.md

オブジェクトの「内部状態」によって振る舞いを切り替える State パターンを、MobStatusStateEnum(Normal / Attack / Die)で解説します。if/switch の羅列を排除し、状態遷移を明確に管理する手法を学びます。

登場クラス

クラス 役割
MobStatus(abstract) StateEnum フィールドで現在状態を保持
MobAttack State == StateEnum.Attack のときだけダメージを与える
EnemyMove State == StateEnum.Die のときに追跡を停止する

学習ポイント

# 学習ポイント
protected enum StateEnum で状態の種類を型安全に列挙する
State プロパティで状態変化を一か所に集約する
各コンポーネントが State を参照して処理をガードする「防衛的プログラミング」
Unity Animator の StateMachine と C# の State パターンの対比
状態が増えたときの拡張しやすさ(enum に値を追加するだけで済む設計)

第6回|プロパティとデータ・ビュー分離

記事ファイル: 06-OOP_プロパティとデータビュー分離.md

C# の get / set プロパティを使って、「データが変わったら自動的に UI が更新される」仕組みを ItemButtonItemsDialog で解説します。MVC / MVP の入り口として、データとビューを疎結合にする設計を学びます。

登場クラス

クラス 役割
ItemButton OwnedItem セッターでアイテムデータを受け取り即座に UI へ反映する
ItemsDialog ItemButtonInstantiate で量産し OwnedItem を渡すだけで画面を構築
OwnedItemsData JSON + PlayerPrefs でアイテムの所持状態を永続化するデータ層

学習ポイント

# 学習ポイント
set アクセサの中で UI 更新メソッドを呼ぶ「プロパティ駆動更新」
[Serializable] + JsonUtility でオブジェクトを JSON 文字列に変換する
PlayerPrefs.SetString / GetString でデバイスに文字列を保存・読み込みする
GetComponentsInChildren<Toggle>() で動的生成した子オブジェクトを一括取得する
データクラス(OwnedItemsData)・UI クラス(ItemButton)・制御クラス(ItemsDialog)を分離するメリット

パターン早見表

パターン名 中心クラス GoF カテゴリ
第1回 Singleton OwnedItemsDataAudioManagerLifeGaugeContainer 生成
第2回 Template Method MobStatusPlayerStatusEnemyStatus 振る舞い
第3回 Delegation + Observer CollisionDetectorUnityEvent<T> 振る舞い
第4回 Single Responsibility PlayerController + 各コンポーネント 原則(SOLID)
第5回 State MobStatus.StateEnumMobAttackEnemyMove 振る舞い
第6回 Data / View 分離 ItemButtonItemsDialogOwnedItemsData 構造

関連シリーズ


最終更新:2026年4月