タイトル: MonoBehaviour
SEOタイトル: Unity MonoBehaviour 完全ガイド
| この記事の要点 |
|
MonoBehaviour とは
MonoBehaviour は Unity のスクリプト機能で最もよく継承する基底クラスです。これを継承した C# クラスは Unity の GameObject に Component としてアタッチでき、フレームごとに自動でメソッドが呼ばれます。
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField] private float speed = 5f;
void Start()
{
Debug.Log("Start: 初回フレーム前に呼ばれる");
}
void Update()
{
float h = Input.GetAxis("Horizontal");
transform.Translate(Vector3.right * h * speed * Time.deltaTime);
}
}
ライフサイクル(呼び出し順)
Unity は MonoBehaviour 派生クラスの特定のメソッド名を、ライフサイクルの各タイミングで自動的に呼び出します。
| メソッド | 呼ばれるタイミング | 用途 |
|---|---|---|
| Awake() | シーン読み込み時、enabled に関係なく 1 回 | 変数初期化、参照取得 |
| OnEnable() | GameObject が有効化されるたび | イベント購読 |
| Start() | 初回 Update 直前、enabled なら 1 回 | 他オブジェクト参照ありの初期化 |
| FixedUpdate() | 固定間隔(既定 0.02 秒 = 50Hz) | Rigidbody 操作・物理 |
| Update() | 毎フレーム | 入力・ゲームロジック |
| LateUpdate() | Update 後・毎フレーム | カメラ追従 |
| OnDisable() | 無効化される直前 | イベント解除 |
| OnDestroy() | 削除される直前 | リソース解放 |
| OnApplicationQuit() | アプリ終了直前 | セーブ処理 |
Update / FixedUpdate / LateUpdate の使い分け
public class Player : MonoBehaviour
{
public Rigidbody rb;
public Camera cam;
void Update()
{
// 入力読み取り、表示更新(フレームレートに依存)
if (Input.GetKeyDown(KeyCode.Space))
Jump();
}
void FixedUpdate()
{
// 物理演算(Rigidbody)は必ずここで
rb.AddForce(Vector3.forward * 10f);
}
void LateUpdate()
{
// すべての Update 後 → カメラ追従に最適
cam.transform.position = transform.position + new Vector3(0, 5, -10);
}
void Jump() => rb.AddForce(Vector3.up * 500f);
}
Inspector への公開: [SerializeField]
Unity Inspector でパラメータ調整可能にするには 2 通り:
public class Enemy : MonoBehaviour
{
// ❌ public で公開(他クラスから書き換え可能 → カプセル化壊す)
public float hp = 100f;
// ✅ [SerializeField] で private のまま Inspector に公開(推奨)
[SerializeField] private float speed = 3f;
[SerializeField] private int damage = 10;
[SerializeField] private GameObject explosionPrefab;
// 範囲制限 / ツールチップも便利
[SerializeField, Range(0f, 100f)] private float volume = 50f;
[SerializeField, Tooltip("敵が消滅するまでの秒数")] private float lifetime = 5f;
// 配列・リストもそのまま公開可能
[SerializeField] private Transform[] waypoints;
}
主要なプロパティ
| プロパティ | 意味 |
|---|---|
gameObject | アタッチされている GameObject |
transform | 位置・回転・拡縮(gameObject.transform の省略) |
enabled | このコンポーネントの ON/OFF |
isActiveAndEnabled | GameObject 有効 + enabled の AND |
name | gameObject.name の省略 |
tag | gameObject.tag の省略 |
Coroutine(コルーチン)
MonoBehaviour 派生クラスでのみ使える、フレームをまたぐ非同期処理:
void Start()
{
StartCoroutine(FadeOut());
}
IEnumerator FadeOut()
{
var renderer = GetComponent();
Color c = renderer.material.color;
for (float t = 0; t < 1f; t += Time.deltaTime)
{
c.a = 1f - t;
renderer.material.color = c;
yield return null; // 次のフレームまで待つ
}
yield return new WaitForSeconds(1f); // 1 秒待つ
Destroy(gameObject);
}
// 停止
StopCoroutine(FadeOut()); // または handle 経由
StopAllCoroutines();
Invoke と InvokeRepeating
void Start()
{
// 3 秒後に Spawn() を呼ぶ
Invoke(nameof(Spawn), 3f);
// 2 秒後から 1 秒間隔で繰り返し
InvokeRepeating(nameof(Tick), 2f, 1f);
// 解除
CancelInvoke(nameof(Tick));
CancelInvoke(); // すべて解除
}
void Spawn() { /* ... */ }
void Tick() { /* ... */ }
SendMessage(非推奨だが理解しておく)
// 文字列でメソッド名を指定して呼ぶ(リフレクション)
gameObject.SendMessage("TakeDamage", 10);
gameObject.BroadcastMessage("Reset"); // 子供にも
gameObject.SendMessageUpwards("OnHit"); // 親にも
// → 遅い・タイプセーフでない・リファクタしにくい
// → 推奨: GetComponent().TakeDamage(10) や Action/UnityEvent
ScriptableObject との違い
| 項目 | MonoBehaviour | ScriptableObject |
|---|---|---|
| アタッチ先 | GameObject | アセットファイル |
| Update / 物理 | あり | なし |
| 用途 | 動作するゲーム要素 | 共有データ / 設定 |
| シーンに依存 | する(GameObject ごと) | しない |
| ビルド後の保存 | シーン保存 | アセット永続 |
| メモリ上のインスタンス数 | GameObject ごと | アセット 1 個 = 1 インスタンス |
パフォーマンスの注意
MonoBehaviour の Update 等は1 万個の GameObject にアタッチすると C++ ↔ C# の呼び出しコストが無視できなくなります。
// ❌ アンチパターン: 1万個に Update
// 各 Enemy.cs に void Update() を持つ → 10000 回 / フレームの C++→C# 呼び出し
// ✅ 推奨: Manager で一括処理
public class EnemyManager : MonoBehaviour
{
private List enemies = new();
void Update()
{
foreach (var e in enemies)
e.Tick(Time.deltaTime);
}
}
public class Enemy // MonoBehaviour を継承しない POCO
{
public void Tick(float dt) { /* ... */ }
}
// または DOTS/ECS で完全に C++ 側で処理
ECS / DOTS との比較
Unity DOTS(Data-Oriented Technology Stack)の ECS(Entity Component System) は MonoBehaviour とは別パラダイム。10 万以上のオブジェクトを高速処理するためのジョブ + バーストコンパイラ前提。
| 項目 | MonoBehaviour | ECS |
|---|---|---|
| パラダイム | OOP | データ指向 |
| メモリ配置 | 個別アロケート | 連続配列 (Chunk) |
| 並列化 | 困難 | Job System で自動 |
| 学習曲線 | 緩い | 急峻 |
| 大量処理 | 遅い | 高速 |
FAQ
Q: Awake と Start の違いは?
A: Awake は GameObject が有効でなくても呼ばれ、すべての Awake の後にすべての Start が呼ばれます。「他オブジェクト参照あり初期化」は Start に書くと安全です。
Q: Update が呼ばれない
A: スペル間違い(update 小文字)、Component 無効、GameObject 無効のいずれか。Inspector でチェックボックスを確認。
Q: new MonoBehaviour() してインスタンス化できる?
A: できません。必ず GameObject に AddComponent する必要があります。gameObject.AddComponent。