Unityで学ぶMVPパターン(2) ~ Viewコンポーネントを複数にする ~

[前の記事](https://qiita.com/Nakashima_Toshiki/items/5e0c36c3b0df78110d32)　－　[目次](https://qiita.com/Nakashima_Toshiki/items/f403b40bea0ad790176c)　－　[次の記事](https://qiita.com/Nakashima_Toshiki/items/b749188ddd649af6f9ac)
前回作ったUniRxで作成したMVPパターンを複数のViewコンポーネントを使えるようにする方法について考察

## 目的

体力(Health)の値に応じて以下の処理を反映したい。

- 体力バーを更新
- テキスト形式で表示
- 体力が低くなると画面の上下に血痕（赤い画像）を表示する

これらをMVPパターンで実装します。

## シーンの作成

以下の画像のようにシーンを作成します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/291470/0d655051-923e-b389-ed0d-e2d946da2273.png)

Githubに準備済みのプロジェクトを上げておきます。
[02-UniRx-HealthBar-MultiView-Base](https://github.com/NakashimaToshiki/Adaptive-Code-Unity/tree/master/02-UniRx-HealthBar-MultiView-Base)

## コンポーネントの作成

MVPパターンのViewにあたるコンポーネントを３種類作成します。
あと、Presenterコンポーネントを複数のViewを登録できるように改造します。

### ParameterViewBase

作成するViewコンポーネントはこのクラスを継承させます。
virtualメソッドを作成して処理は空にします。

```C#:ParameterViewBase.cs
using UnityEngine;

public class ParameterViewBase : MonoBehaviour
{
    virtual public void SetParameter(int max, int value)
    {
    }
}
```

### ParameterBar

以前作ったParameterBarコンポーネントを改造。

ParameterViewBaseを継承させ、
SetParameterメソッドはoverride修飾子をつけます。

```C#:ParameterBar.cs
using UnityEngine;

public class ParameterBar : ParameterViewBase
{
    public RectTransform valueRect;

    override public void SetParameter(int max, int value)
    {
        valueRect.localScale = new Vector3((float)value / max, 1, 1);
    }
}

```
### ParameterText

体力の最大値と現在値をテキスト表示します。

```C#:ParameterText.cs
using UnityEngine.UI;

public class ParameterText : ParameterViewBase
{
    public Text valueText;

    override public void SetParameter(int max, int value)
    {
        valueText.text = value + " / " + max;
    }
}
```
### ParameterImage

画面上下のImage画像パネルにアルファ値を設定します。
体力が低くなると赤いイメージ画像が表示するようになります。

```C#:ParameterText.cs
using UnityEngine;
using UnityEngine.UI;

public class ParameterImage : ParameterViewBase
{
    public Image valueImage;

    override public void SetParameter(int max, int value)
    {
        var color = valueImage.color;
        valueImage.color = new Color(color.r, color.g, color.b, Mathf.Lerp(1, 0, (float)value / max));
    }
}
```
### ParameterPresenter

以前作ったParameterPresenterクラスのview変数を配列に変更。

ParameterViewBase[] 変数配列は
ParameterViewBaseを継承したクラスを登録することができます。

Awakeメソッドにて登録したクラスのSetParameterメソッドは
UniRxによりHealth値の変更時に実行されるようになります。

```C#:ParameterPresenter.cs
using UnityEngine;
using UniRx;

public class ParameterPresenter : MonoBehaviour {

    public StatusModel model;

    public ParameterViewBase[] healthViews;

    void Awake()
    {
        foreach (var view in healthViews)
        {
            model.healthRP.Subscribe(value => { view.SetParameter(model.healthMax, value); });
        }
    }
}
```
## コンポーネントの追加

以下の画像のように作成したコンポーネントをゲームオブジェクトに追加します。

ParameterImageコンポーネントは上下のイメージ画像に追加するので、２つのゲームオブジェクトに存在します。

あとは、コンポーネントの依存状態をドラッグ＆ドロップで設定して完成。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/291470/b5e82ed4-c05a-0afd-cba8-5ff529fa5b04.png)

## 完成

inspectorからHealth Rxの値を変えると

- 体力バーの長さが変わる
- テキスト表示が更新される
- 画面上下が赤くなる

で３種類のViewが反映されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/291470/cf55e8d9-d96d-fcbb-f5e2-2a411028a6b5.png)

Githubに完成プロジェクトを上げておきます。

[03-UniRx-HealthBar-MultiView](https://github.com/NakashimaToshiki/Adaptive-Code-Unity/tree/master/03-UniRx-HealthBar-MultiView)

## まとめ

ParameterViewBaseを継承したコンポーネントはすべて
ParameterPresenterコンポーネントに依存を追加するだけで
値の変化と見た目の変化を連動することができます。

自分が作っているゲームにで
Updateメソッドが膨れ上がり拡張しづらいと感じた場合、
MVPデザインパターンを実装してみることを検討してみてください。