目次
はじめに
はじめまして、SGと申します。
主にUnityを使ってゲームとか作っています。
設計が好きなのでしばらくはUnity,C#,設計関係の投稿をしようと思っています。
筆者は設計初心者です。
間違いや独自のとらえ方も多いためなるべく疑って読んでください。
MVPとは
まずMVPパターンの説明をさせていただきます。
MVPパターンとはある実装を以下の3つにわけるような実装方法のことです。
- Model : データの保持とデータを扱うロジックをもつ
- View : データの表示やアニメーションを行う
- Presenter : ModelとViewの橋渡しを行う
このようにPresenterはModelとViewをもち、Modelのデータの変更があると、更新してViewに渡すようにします。
実際のコードと共に確認していきます。今回実装するのはHPを実装します。
Model
HPのModelとしてデータにはHPというデータがあります。ロジックにはダメージを受けること、回復することこの2つがあります。
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の量が変化するときのアニメーションがあります。
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に渡す機能が存在します。
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のコードを書きます。
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のコードも変更します。
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の説明だけ難易度高すぎではと思う今日このごろです
