🔰
【Unity,C#】MVPパターン入門【GIFアリ】
関連記事
背景と補足
- MVPというのを時々聞く。特にUI周りで有効だとか(依存関係の整理)
- 学習する!!!
MVPとは何か
- 実装対象のプログラムをModel, View, Presenter に分けて設計するパターン
- Model:データ,更新ロジックを保持(例:体力、スコアなど)
- View:UIの見た目を担当、入力をPresenterに通知
- Presenter:入力を受け取りModelを制御、Modelの状態に応じてViewを更新
どんなときに有効?
-
UIの状態,表示が複雑なロジックに依存(例:HP,スコア,インベントリ表示)
- 状況に応じてUIを更新する処理が複雑になりがち
- View単体で処理するとデータの参照,描画が混在
-
同じModelを異なるViewで再利用したい(例:簡易,詳細ウィンドウで同じデータを表示)
- 1Modelのロジックを複数のViewに反映できる
-
画面遷移や状態遷移をしたい(例:チュートリアルのUI)
- Model:状態の履歴,条件,ロジック保持
- View:UI表示,非表示
- Presenter:状態遷移の管理者になり、画面構成を整理
-
外部のゲームロジックと連携したい場合(例:攻撃を受けてHPバー減少)
- Presenterが外部との窓口になり、Model,Viewの内部を知られずに制御できる
- このように、外部からの操作や通知もPresenter経由にすると、疎結合が保てる
どんなときに向かない?
-
小規模 or 単発のロジック
- それ、3クラスもいる? と思ったら注意
この後の実装例こそそうだったりする
実装例
- 「画像クリック時に画像の色をランダムに変更する」機能を実装する
-
【Unity,C#】イベント駆動入門【UniRx,R3不使用】 と同じ例
MVPパターンを取り入れない場合
- 入力検知側
public class ClickBroadcaster : MonoBehaviour, IPointerClickHandler
{
public static event Action OnButtonClicked;
public void OnPointerClick(PointerEventData eventData)
{
OnButtonClicked?.Invoke();
}
}
- UI側
public class ColorChanger : MonoBehaviour
{
[SerializeField] private Image img;
private void OnEnable()
{
ButtonClickBroadcaster.OnButtonClicked += ChangeColor;
}
private void OnDisable()
{
ButtonClickBroadcaster.OnButtonClicked -= ChangeColor;
}
private void ChangeColor()
{
img.material.color = Random.ColorHSV();
}
}
-
InputManager
がイベント発行、ButtonSystem
が購読を行う
MVPパターンを取り入れる場合
- Model (アタッチ先:ナシ)
public class ColorModel
{
public Color CurrentColor { get; private set; }
public void GenerateNewColor()
{
CurrentColor = Random.ColorHSV();
}
}
- View (アタッチ先:Imageコンポーネントを持つオブジェクト)
public class ImageView : MonoBehaviour, IPointerClickHandler
{
public event Action OnClicked;
[SerializeField] private Image image;
public void OnPointerClick(PointerEventData eventData)
{
OnClicked?.Invoke();
}
public void SetColor(Color color)
{
image.color = color;
}
}
- Presenter (アタッチ先:ナシ)
public class ImagePresenter
{
private readonly ImageView view;
private readonly ColorModel model;
public ImagePresenter(ImageView view, ColorModel model)
{
this.view = view;
this.model = model;
view.OnClicked += OnViewClicked;
}
private void OnViewClicked()
{
model.GenerateNewColor();
view.SetColor(model.CurrentColor);
}
}
- MVPの初期化,Presenter保持 (アタッチ先:適当なオブジェクト)
public class GameRoot : MonoBehaviour
{
[SerializeField] private ImageView view;
private ImagePresenter presenter;
private void Start()
{
var model = new ColorModel();
presenter = new ImagePresenter(view, model);
}
}
比較
- MVPなし:UIが直接イベント処理を持つ
- MVP:Presenterがロジックを中継する
MVPパターンのメリットまとめ
-
責務をより分離できる
- 表示処理はView、データはModel、制御はPresenter
- Presenterにより、View,Modelがお互いに仕様変更の波及を受けにくい
-
再利用性が高い
- 同じModelに対し、View,Presenterを複数使い分けられる
- Viewの再利用性が高い → Prefabの再利用性も高い
-
例:ImageView → ImagePresenter → ColorModel の連携
- ImageView:クリック通知
- ImagePresenter:ロジックを中継し、色を生成
- ColorModel:色状態を管理
各要素が互いを直接参照しないことで、柔軟に入れ替え可能
Discussion