【Unity】MonoBehaviourに書きすぎてはいけない理由

Unity初心者が必ずハマる設計の落とし穴

Unityでゲームを作り始めると、多くの人がこうなります。

「とりあえずMonoBehaviourに全部書けば動くし、問題なくない?」

結論から言うと、最初は動くけど、必ず後で詰みます。

この記事では、

  • なぜMonoBehaviourに書きすぎてはいけないのか

  • 実際に何が困るのか

  • 初心者でもできる改善方法

等々紹介していきたいと思います。

よくあるMonoBehaviour地獄の例

まずは典型的な失敗例です。

public class Player : MonoBehaviour
{
    void Update()
    {
        Move();
        Jump();
        Attack();
        CheckHP();
        SaveData();
        PlaySound();
        UpdateUI();
    }

    void Move() { }
    void Jump() { }
    void Attack() { }
    void CheckHP() { }
    void SaveData() { }
    void PlaySound() { }
    void UpdateUI() { }
}

一見すると問題なさそうですが、
この時点ですでに危険信号が出ています。

理由①:責務が多すぎて「何をするクラスか分からない」

Playerクラスがやっていることを整理すると

  • 入力処理

  • 移動処理

  • 攻撃処理

  • HP管理

  • セーブ

  • サウンド再生

  • UI更新

と多すぎます。

何が問題?

  • クラス名と中身が一致しない

  • 修正時に「どこを触ればいいか分からない」

  • 機能追加が怖くなる

これはプログラミングでいう責務過多状態です。

理由②:再利用できないコードになる

例えば敵キャラを作りたくなったとします。

「Playerの攻撃処理、Enemyでも使いたいな・・・」

 

でも、

  • Player専用の変数

  • UI更新が混ざっている

  • 入力処理が直書き

こうなっていると流用できません。

結果として

  • コピペする

  • 少し直す

  • バグる

  • さらにコピペ

と、地獄の始まりになりかねません。

理由③:テスト・修正が極端にしづらい

MonoBehaviourはUnityに強く依存しています。

  • Update()

  • GameObject

  • Transform

  • SerializeField

そのため、

  • ロジック単体で確認できない

  • バグの原因を切り分けられない

  • 変更が連鎖的に壊れる

「少し直しただけなのに別の挙動が壊れた」という経験、ありませんか?

理由④:Update地獄に陥る

MonoBehaviourに書きすぎる人の多くがこうなります。

void Update()
{
    // 毎フレーム必要ない処理
    CheckSave();
    UpdateUI();
    SearchEnemy();
}

問題点

  • 毎フレーム実行される必要がない

  • パフォーマンス低下

  • どこが重いのか分からない

「とりあえずUpdate」思考が生まれる

じゃあどう書けばいいの?

基本原則:MonoBehaviourは「つなぎ役」

MonoBehaviourは、

  • Unityとの接点

  • 入力・イベントの受け口

  • 初期化・更新の管理

だけを担当させます。

処理の中身は別クラスへ

改善例:ロジックを分離する

悪い例(全部MonoBehaviour)

public class Player : MonoBehaviour
{
    int hp;

    void Damage(int value)
    {
        hp -= value;
    }
}

良い例(ロジック分離)

public class Player : MonoBehaviour
{
    PlayerHP hp;

    void Awake()
    {
        hp = new PlayerHP(100);
    }

    void Damage(int value)
    {
        hp.Damage(value);
    }
}

public class PlayerHP
{
    int hp;

    public PlayerHP(int maxHP)
    {
        hp = maxHP;
    }

    public void Damage(int value)
    {
        hp -= value;
    }
}

こうなると何が良い?

  • PlayerHPはUnityに依存しない

  • テストしやすい

  • 他キャラにも使える

  • 修正が安全

初心者向け:最低限これだけ守ればOK

いきなり完璧を目指す必要はありません。

まず意識すること

  • MonoBehaviour = 管理・接続役

  • 計算・判定・ルール = 普通のクラス

分ける目安

  • 「これはUnityじゃなくても動く?」
    → YESなら別クラス

よくある勘違い

「初心者には難しすぎる」

むしろ後から直す方が100倍大変

「小規模だから大丈夫」

→ 小規模でも確実に汚れる

「動いてるからOK」

→ 動く ≠ 正しい設計

まとめ

  • MonoBehaviourに書きすぎると

    • クラスが肥大化する

    • 再利用できない

    • 修正が怖くなる

    • Update地獄に陥る

  • MonoBehaviourは「つなぎ役」

  • ロジックは普通のC#クラスへ

    著者プロフィール
    うんくん

    IT系に特化した記事がメインです。(Unity多め。)
    Udemy講師もやっています。よろしくお願いします。

    ※Amazonのアソシエイトとして、当メディアは適格販売により収入を得ています。

    うんくんをフォローする
    unityunity基本操作
    シェアする
    うんくんをフォローする