[Unity] 入門講座 #02 : MonoBehaviour は何者か

はじめに

前回までで、Unity が「普通の C# プログラム」と違う理由、そして GameObject と Component の関係を整理した。 ここからようやく “Unity のスクリプトが動く正体” に触れる。

それが MonoBehaviour だ。

ただし、多くの初心者が勘違いしている。

MonoBehaviour を継承するのは「便利な機能を追加するため」ではない。

この記事では、MonoBehaviour の本質を“Unity のイベントループとの接続”という視点から解説する。

1. MonoBehaviour は“継承で機能を増やすクラス”ではない

C# の文法だけを見ると、class X : MonoBehaviour は普通の継承だ。 しかし、MonoBehaviour の継承は C# の継承とは目的そのものが違う。

一般的な継承はこうだ。

  • 通常の継承 親クラスの機能を受け継ぎ、必要に応じて拡張する。

一方、MonoBehaviour の継承はこう解釈するべきだ。

  • MonoBehaviour の継承 Unity に「このクラスをイベントループに参加させていい」と知らせるための声明。

つまり MonoBehaviour を継承する目的は、 「新しい機能を追加するため」ではなく、「Unity の管理下に入るため」 だということ。

ここを誤解すると、MonoBehaviour を“便利機能セット”のように扱ってしまい、C# のクラスデザインと Unity の設計思想が混ざって理解が崩れる。

なぜ「Unity に管理される」ことが重要なのか?

MonoBehaviour を継承した瞬間、そのクラスは Unity の実行ループ(Awake → Start → Update → …)の対象になる。 つまり、Unity がゲーム実行中に自動で呼び出す一連の “ライフサイクルイベント” の受け口になる。

MonoBehaviour を継承する = Unity の世界に存在するための資格を得る

ここが、普通の C# クラスとの最も大きな違いだ。

1.1 C# の継承の常識が Unity では通じない

通常、継承とは 「親クラスの機能を引き継ぎ、 override で振る舞いを差し替えて拡張する」 という仕組みだ。

しかし MonoBehaviour は、この目的で使う継承ではない。

  • virtual も override も使わない
  • 機能もほとんど提供しない
  • 差し替える前提のロジックも存在しない

「継承なのに継承っぽい使い方をしない」 ここがまず異質。

1.2 MonoBehaviour は「イベントループへの登録タグ」

MonoBehaviour を継承する目的は、

“Unity のイベントループに参加する資格を得る”こと。

この継承をつけた瞬間、クラスは Unity の管理リストに入り、

  • Awake
  • Start
  • Update
  • OnCollisionEnter などのコールバックを受け取れるようになる。

機能が増えるのではなく、

Unity が「このクラスに通知していい」と判断するための“登録タグ”

として機能している。


1.3 なぜ Unity は new を禁止するのか

MonoBehaviour は new すると壊れる。 これは C# 的には奇妙だが、Unity では正しい。

理由はシンプルで、

“Unity が生成しないと、Unity が管理できない” “管理できないものに Update は送れない”

から。

new した MonoBehaviour は:

  • シーンに存在しない
  • GameObject と結びつかない
  • Awake/Start/Update が呼ばれない
  • Inspector の設定も反映されない

つまり Unity の世界に存在すらしない幽霊 になる。

だから new を禁止している。


1.4 ポリモーフィズムを使わない異例の継承

MonoBehaviour の継承は「型の関係」ではなく「Unity の仕組みとの接続」のために使われる。

  • 親クラスのロジックを差し替えるわけじゃない
  • 継承階層を活かして設計しない
  • 子クラス同士のポリモーフィズムはほとんど使わない

言い換えると、

「オブジェクト指向の継承」をしているのではなく、 「Unity の世界に参加するフラグ」を立てている

と思った方が正しい。


1.5 「Unity が管理するオブジェクト」としての区別

MonoBehaviour を継承したクラスは、 “Unity の管理下で動く存在” として扱われる。

  • GameObject にアタッチされる
  • シーンに存在する
  • Inspector で編集可能
  • Unity のイベントを受け取る
  • ライフサイクルに従って動く

一方、普通の C# クラスは:

  • new で自由に作れる
  • データ・ロジックとして扱う
  • イベントを受け取れない
  • Unity から見えない

この“世界の内側と外側”の区別こそ MonoBehaviour の役割であり、 継承というより“Unity の世界への参加証”に近い。


まとめ

MonoBehaviour は 「機能を追加するための親クラス」ではなく、 「Unity に管理されるための登録タグ」 である。

その結果、

  • new ができない
  • イベントが自動で届く
  • GameObject にアタッチして初めて実体になる

という Unity 特有の振る舞いが生まれる。

2. Unity のイベントループに参加する“資格”を与えるもの

2.1 Unity が“呼び出す側”、あなたのスクリプトは“呼ばれる側”

MonoBehaviour を継承したスクリプトは、特定のメソッド名を定義しておくだけで、 Unity がゲーム実行中に自動的に呼び出してくれる。

代表的なものはこれだ:

  • Awake:生成直後に1回だけ呼ばれる
  • Start:初回のフレームで呼ばれる
  • Update:毎フレーム呼ばれる
  • FixedUpdate:物理ループごとに呼ばれる
  • OnEnable / OnDisable:有効化 / 無効化のたびに呼ばれる
  • OnCollisionEnter / OnTriggerStay:物理イベント
  • OnDestroy:破棄される直前に呼ばれる …など多数。

ここで重要なのは、

これらは“自分で呼ぶものではない”という設計になっていること。

C# の文法上は普通のメソッドだけど、 Unity 側が特別扱いしていて、ライフサイクルに沿ってコールバックを送っている。

2.2 MonoBehaviour は「通知の受け口」になるための型

MonoBehaviour を継承することで、そのクラスは Unity のイベントループに登録される。 これによって、Unity はこう考える:

「このコンポーネントに Update を送っていい」 「このオブジェクトは Awake/Start を受け取る対象だ」

もし MonoBehaviour を継承していないとどうなるか?

  • Update は呼ばれない
  • Awake/Start も呼ばれない
  • OnTrigger も OnCollision も届かない
  • GameObject に紐付けても動かない

つまり、

ただの C# クラスには、Unity は一切通知を送らない。

MonoBehaviour を継承しているかどうかが、 「Unity の世界に存在できるコンポーネントかどうか」 の境界線になっている。

2.3 Unity から見れば「イベント配信先を決めるフィルター」

Unity は毎フレーム、ものすごい数のコンポーネントにイベントを送っている。

しかし、なんでもかんでも呼んでいるわけではない。

  • MonoBehaviour を継承したクラス
  • かつ GameObject にアタッチされている
  • かつ active / enabled の状態である

この条件を満たしたものだけが、 “イベントの受信リスト” に載る。

つまり MonoBehaviour は、

Unity が「誰にイベントを送るか」を判断するためのフィルター

とも言える。

まとめ

  • MonoBehaviour を継承したクラスは Unity が自動で呼び出す対象になる
  • Awake / Start / Update などのメソッドは 自分で呼ぶものではなく、Unity の通知コールバック
  • ただの C# クラスには 一切イベントは届かない
  • MonoBehaviour はイベントループに参加するための “資格” を与えるもの

3. 「Update」は勝手に呼ばれるわけではない:呼ばれる条件

多くの解説では「Update は毎フレーム呼ばれます」で終わってしまう。 しかし実際には、Update が呼ばれるには 複数の条件 が揃っている必要がある。

Unity のイベントループは “自動で動く” が、 “無条件” に呼び続けているわけではない。

3.1 GameObject が active である

シーン上で非アクティブ状態(チェックを外した状態)の GameObject は、 Unity の更新対象から完全に外れる。

→ Update は一度も呼ばれない。


3.2 Component(スクリプト)が enabled である

Inspector のチェックボックスを外すと、そのコンポーネントは無効になる。

→ Update も含め、すべてのコールバックが停止する。


3.3 MonoBehaviour を継承したスクリプトがアタッチされている

ただクラスを定義しただけでは何も起きない。

→ GameObject にアタッチされて初めて “存在” として扱われる。


3.4 シーン内に存在している

プレハブはあくまで “設計図”。 インスタンス化されていなければイベントは届かない。

→ プレハブ単体には Update は来ない。


3.5 プレイモード中である

エディタ上のプレビューや編集状態では、 Unity の実行ループ自体が動いていない。

→ Update はプレイモード限定のイベント。

1つでも欠けると Update は止まる

Update が呼ばれない原因の多くは、 「スクリプトが壊れている」わけではなく、単にどこかの条件が満たされていないだけ。

初心者が最もつまずくポイントなので、 “動かないときにチェックすべきチェックリスト” として覚えておくと失敗が激減する。

4. 普通の C# クラスとの違い

ここまでの内容を踏まえて、MonoBehaviour が “普通の C# クラス” とは根本的に違う存在であることを整理する。

Unity の中では、クラスは大きく 2種類 に分かれている。


MonoBehaviour を継承しないクラス(ただの C# のクラス)

  • new で自由に生成できる
  • データクラス、ユーティリティ、ロジック処理として使える
  • Unity のイベント(Update など)は届かない
  • GameObject にアタッチできず、シーン上に存在できない

これは C# の通常ルールそのままのクラス。


MonoBehaviour を継承するクラス(Unity 管理下のクラス)

  • new できない(new しても Unity が管理できないので機能しない)
  • GameObject にアタッチして初めて“存在”になる
  • Awake / Start / Update などの Unity イベントを受け取れる
  • シーン内で実体として置かれ、Inspector で編集できる

「Unity が認識し、管理し、イベントを送る対象」として扱われる。


まとめ:MonoBehaviour は“機能を持つ親クラス”ではない

ここまでの差をまとめると分かりやすい。

MonoBehaviour は “クラスの種類” ではなく “Unity の世界に取り込まれるためのフック” に近い。

C# 的な継承ではなく、 Unity の管理システムとイベントループに登録するための宣言 こそが MonoBehaviour の役割であり、本質となる。

5. MonoBehaviour の“できること / できないこと”

ここまでの内容を踏まえ、MonoBehaviour が担う役割と、その制約をまとめておく。 MonoBehaviour は Unity の管理下にある特殊な存在 であり、この前提が“できること / できないこと”の根拠になっている。

5.1 Unity のイベントを受け取る

Awake / Start / Update / OnCollision など、 Unity のライフサイクルイベントを自動的に受け取れる。

5.2 Inspector にフィールドを公開できる

public[SerializeField] をつけるだけで、 Inspector 上で設定値として扱える。

5.3 GameObject に紐づく“振る舞い”を作れる

位置・移動・操作・エフェクトなど、 シーンで実際に動くロジックを担当する。

5.4 実体としてシーンに存在できる

Component としてアタッチされ、 Unity の更新対象として動作する。


MonoBehaviour ができないこと

1. new でインスタンス化して運用する

new では Unity に管理されないため、 ライフサイクルもイベントも動かない“幽霊オブジェクト”になる。

2. コンストラクタでゲームロジックを開始する

Unity はコンストラクタをライフサイクルとして扱わない。 ゲーム開始は Awake / Start から。

3. 継承で機能追加する一般的な C# の設計

MonoBehaviour はオブジェクト指向的な継承でなく、 Unity との接続タグとして使われるため、 継承を中心に拡張する設計とは相性が悪い。

まとめ

これらの性質はすべて、

MonoBehaviour は Unity に管理されるための特別なクラスである

という前提から生まれている。

普通の C# クラスと同じ感覚で扱うと混乱が起きるが、 “Unity の世界に参加するためのフック” と理解すれば、 MonoBehaviour の制約と振る舞いは自然に説明がつく。


必要ならこの後に シリーズ全体のまとめ も書ける。

まとめ

MonoBehaviour は、C# の継承の文脈では理解しきれない “Unity 特有の存在” だ。 その役割と制約は、すべて 「Unity のイベントループに参加するため」 という一点から生まれている。

  • MonoBehaviour の目的は Unity のイベントループに参加すること
  • 継承しても“機能が増える”わけではない
  • Update などのコールバックは、Unity が 条件を満たしたときだけ 自動で呼び出す
  • new やコンストラクタ中心の C# 的な考え方とは根本的に異なる
  • GameObject と Component の理解と組み合わせて、初めて全体像が見えてくる

MonoBehaviour は “Unity の世界に属するためのフック” である。 これを押さえることで、「なぜ Unity のスクリプトはこう動くのか?」という根本が一気に理解しやすくなる。