はじめに
前回までで、Unity が「普通の C# プログラム」と違う理由、そして GameObject と Component の関係を整理した。 ここからようやく “Unity のスクリプトが動く正体” に触れる。
それが MonoBehaviour だ。
ただし、多くの初心者が勘違いしている。
MonoBehaviour を継承するのは「便利な機能を追加するため」ではない。
この記事では、MonoBehaviour の本質を“Unity のイベントループとの接続”という視点から解説する。
[Unity] 入門講座 #01 : GameObject と Component の本質的な関係
Unityで最初にぶつかる違和感──クラスを書いても動かない理由、アタッチの意味、Inspector が存在する根拠を、GameObject と Component の関係から整理する基礎講座。
https://humanxai.info/posts/unity-basics-01-gameobject-and-component/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 のスクリプトはこう動くのか?」という根本が一気に理解しやすくなる。
💬 コメント