10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

UnityでMVPパターンを使ってみた

Posted at

目次

はじめに

はじめまして、SGと申します。
主にUnityを使ってゲームとか作っています。
設計が好きなのでしばらくはUnity,C#,設計関係の投稿をしようと思っています。

筆者は設計初心者です。
間違いや独自のとらえ方も多いためなるべく疑って読んでください。

MVPとは

まずMVPパターンの説明をさせていただきます。
MVPパターンとはある実装を以下の3つにわけるような実装方法のことです。

  • Model : データの保持とデータを扱うロジックをもつ
  • View : データの表示やアニメーションを行う
  • Presenter : ModelとViewの橋渡しを行う

MVPtoha.png

このようにPresenterはModelとViewをもち、Modelのデータの変更があると、更新してViewに渡すようにします。
実際のコードと共に確認していきます。今回実装するのはHPを実装します。

Model

HPのModelとしてデータにはHPというデータがあります。ロジックにはダメージを受けること、回復することこの2つがあります。

.cs
public class HPModel {
    public int HP { get; private set; }
    public HPModel() {
        HP = 100;
    }
    public void Damage(int damage) {
        HP -= damage;
        if (HP < 0) {
            HP = 0;
        }
    }
    public void Heal(int amount) {
        HP += amount;
        if (HP > 100) {
            HP = 100;
        }
    }
}

このようにHeal、Damageが実装されました。
またデータの受け渡しのためにgetter,setterを設定しました。

このときHPのsetterをpublicにすると外部からHPを直接変えられてしまうためsetterはprivateにしましょう

View

ViewにはTextというオブジェクトがあり、さらにHPの量が変化するときのアニメーションがあります。

.cs
public class HPView:MonoBehaviour {
    [SerializeField] private Text hpText;
    private int defaultFontSize = 24;
    private int minFontSize = 12;
    public void UpdateHP(string hp) {
        hpText.text = "HP: " + hp;
        UpdateAnimation();
    }
    private void UpdateAnimation() {
        hpText.fontSize = minFontSize;
        DOTween.To(() => hpText.fontSize, x => hpText.fontSize = x, defaultFontSize, 0.5f).SetEase(Ease.OutBack);
    }
}

このようにTextのフォントサイズや数字を変化させることで表示、アニメーションを行います。

Presenter

PresenterはViewとModelをもっています。さらにModelのデータをViewに渡す機能が存在します。

.cs
public class HPPresenter:MonoBehaviour {
    private HPModel model;
    [SerializeField] private HPView view;

    public void Initialize() {
        model = new HPModel();
        view.UpdateHP(model.HP.ToString());
    }
}

実装はできましたが、これではModelのデータが変更されてもViewには反映されません

MV(R)P

上の問題を解決するためにR3(UniRx)を用います。今回用いるR3のReactivePropertyの簡単な説明と変更するModelのコードを書きます。

HPModel.cs
public class HPModel {
    private ReactiveProperty<int> hp;
    public ReadOnlyReactiveProperty<int> HP => hp;
    public HPModel() {
        hp = new ReactiveProperty<int>(100);
    }
    public void Damage(int damage) {
        hp.Value -= damage;
        if (hp.Value < 0) {
            hp.Value = 0;
        }
    }
    public void Heal(int amount) {
        hp.Value += amount;
        if (hp.Value > 100) {
            hp.Value = 100;
        }
    }
}

これに伴ってPresenterのコードも変更します。

HPPresenter.cs
public class HPPresenter:MonoBehaviour {
    private HPModel model;
    [SerializeField] private HPView view;

    public void Initialize() {
        model = new HPModel();

        model.HP.Subscribe(_ => {
            view.UpdateHP(model.HP.Value.ToString());
        }).AddTo(this);
    }
}

このように変更することで、Modelのデータが変更されたときPresenterが購読してViewのメソッドが動きます。これによってViewに反映することができます。

ReadOnlyReactivePropertyを用いることでgetter,setterのようにすることができます。

まとめ

MVPパターンを用いることでロジックのModel、表示、アニメーションのViewに分けることができ読みやすいコードになると思います。

さいごに

UnityにおいてMVPパターンを適用して実装してみました。MVP以外にもMVC,MVVMもありこれの違いとかもお話できればと思っていたのですが、それはまたの機会に!
次の投稿はSOLID原則あたりをやろうかと考えていますが、Dの説明だけ難易度高すぎではと思う今日このごろです

10
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?