2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2018-10-07

前の記事 - 目次 - 次の記事

Unityで学ぶMVPパターン(2) ~ Viewコンポーネントを複数にする ~
でCompositeパターンを使ったほうが良いと思ったので、記事の追記・修正です。

目的

MVPパターンでViewコンポーネントを複数対応化のため、
Presenterのview変数を配列化する必要があるという欠点があった。

Compositeパターンでこの問題を解決したい。

シーンの用意

シーンは前の使いまわしです。

image.png

Githubにプロジェクトを置いておきます。
04-PropertyChanged-HealthBar

コンポーネントの作成

Presenterを修正してCompositeコンポーネントを新たに作成します。

ParameterPresenter

配列型だったview変数を単体の変数に戻します。
この変数に後述で作成するCompositeコンポーネントを登録します。

ParameterPresenter.cs
using UnityEngine;
using System.ComponentModel;

public class ParameterPresenter : MonoBehaviour {

    public StatusModel model;

    public ParameterViewBase healthView;

    void Awake()
    {
        model.PropertyChanged += Model_PropertyChanged;
        Model_PropertyChanged(model, new PropertyChangedEventArgs("")); // 開始時に値を発生させる用
    }

    private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        healthView.SetParameter(model.HealthMax, model.Health);
    }
}

ParameterViewComposite

こちらがCompositeパターンを実装するコンポーネントです。

ParameterViewBaseを継承して、且つParameterViewBaseのコレクションを所持していることがミソです。
このパターンは再帰的な処理をする役割を持っており、
SetParameterメソッドは、リストにある全てのSetParameterも呼び出す仕組みになっています。

つまり、これでPresenter側はCompositeコンポーネントからSetParameterを呼び出せば、
複数のViewを更新することができます。

当然ですが、PresenterはView単体でも登録可能なので、適応性がグンッと上がります。

ついでに、AddComponentInChildrenメソッドを作成して、このコンポーネントがあるゲームオブジェクトの子からParameterViewBaseコンポーネントを継承したコンポーネントを検索して、childrenリストに追加するプログラムを作成します。

GUIのルートオブジェクト(Canvasオブジェクト)に、このコンポーネントを追加しておいて、
、コンポーネント上のコンテキストメニューから実行すれば、リスト生成の手間が省けます。
(ZenjectとかのDIコンテナフレームワークにある自動で依存性を注入する機能に似ている?)

ParameterViewComposite.cs
using System.Collections.Generic;
using UnityEngine;
using System.Linq;

public class ParameterViewComposite : ParameterViewBase
{
    public List<ParameterViewBase> children;

    [ContextMenu("AddComponentInChildren")]
    public void AddComponentInChildren()
    {
        gameObject.GetComponentsInChildren<ParameterViewBase>(children);
        children.Remove(this);
    }

    public override void SetParameter(int max, int value)
    {
        children.ToList().ForEach(child => child.SetParameter(max, value));
    }
}

完成

結果は前回と変わらず、inspectorからHealthの値を変えると

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

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

image.png

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

07 Composite-HealthBar

まとめ

MVPパターンでViewコンポーネントを複数対応化の際に
Presenterのview変数を配列化する修正が必要だったのが、
これで解決しました。

Compositeパターンのリストに
登録しているViewをアクティブにして、
登録していないViewは非アクティブにすれば、
動作しているGUIのみ表示するといったことができそう。

それを実現する良さげなパターンが見つかったら、また記事にしたいです。

2
4
0

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
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?