sh1’s diary

プログラミング、読んだ本、資格試験、ゲームとか私を記録するところ

Unity MVP パターンを利用した UI 設計

f:id:shikaku_sh:20210205155735p:plain

この記事は torisoup さんの「UniRX/UniTask 完全理解」P318 の MVP パターンについて個人的に学習内容をメモする記事です。

MVP パターン is なに?

UI を実装するときの実装パターンです。WPF だと MVVM とかを利用しているやつです。

Virtual Cast の記事だと、「クラスの責務や依存関係が整理される」みたいな話からになっていますが、あくまで目的は「UI を実装するときの実装パターン」のはずです。

UI を実装するときに、実装を3つのタイプで役割を分類します:

  • Model「UI に表示するデータの実体(クラス)」
  • View「uGUI コンポーネントってことでいい(見た目)」
  • Presenter「Model と View の仲介(クラス)」

相互参照を避けるために M と V は P を知らず、P は M と V を知っています。理屈では、バインディングの仕組み(が無いのにそれ)をやる以上、どこかでだれかが V を知っている必要があって(View の更新をするために)、そのために Presenter という概念が用意されています。

この結果、それぞれの役割が整理されて「コードの保守性・生産性を保つ」「改変(変更)に対しての柔軟性を保つ」ようにしようね、という設計デザイン。

Model は POCO なオブジェクトか?

Model は Plain Old CLR Object (POCO) じゃないとモヤッとする、というような記事もありました。(MVP の考え方についての記事です)

MVPはMonobehaviourの依存から解き放たれた設計ができるのに、ModelやPresenterも全てMonobehaviourに依存してしまっているのが勿体無いと思いました。(記事中より)

Unity の Model(M) は特定のフレームワーク、大体は UniRx と結婚しています。(ReactiveProperty を使うわけで)なので、その時点で、Model は Unity に依存したゲームオブジェクトだと思っておいて差し支えないと思います。なんで、いまさら Monobehaviour がどうだと話をしてもという気がしますし、そもそも Presenter はそういう役としか。(下図は「CA.Unity #1 - Unityにおける設計パターン」)

おそらく(上の「どれが正しいんだ?」記事で暗に)意図しているのは「Unity の API」と「C# の言語機能」で切りかけて設計をしたいようにも思います。(思いました)



でも実際は大体こうなると思う。


ハイブリッドなやり方として、左と右にわけると:

  • 左辺は Unity 領域。疎結合な Game Object が書いてある。
  • 右辺はゲームロジック。ロジックなので、POCO でピュアな C# で書いてある。

そんなわけで、MVP の基本要素は左辺中心ってことでいいと思う。ピュアなゲームロジックは ReactiveProperty で書きませんし必要としないです。ピュアなゲームロジックを提供する部分をライブラリーなんかにするのはよいと思う。(けど、M は UI に表示するデータの実体なので、UI を構成するデータ同士は疎結合になっても、Unity のフレームワークとは結婚せざるをえないのではないかと)

neuecc さんのモデル例(enemy)もライブラリーと密です。(文中の内容だと「Model自体はPresenterにも依存しないし、Viewは知らない。ただしViewまで伝搬するため通知は可能でなければならない。」)そもそもこの種の手法はクラスの数が結構と増える設計なんで、M をゲームロジックのクラスじゃなくてもいいじゃん、ってなる。無駄にインターフェースを定義するのだ、ってなる。

より疎結合化を図ると、M は V だけではなくゲームロジックとも密結合にせずに、画面で必要になるパラメーターをインターフェース経由で取得するようと思うかも。でも、変更に対してある程度の柔軟さがあるなら、その必要の有無は考えるところ。実際的に、なにが正しいのかという答えに唯一神はいない。


MVP は「UI を実装するときの実装パターン」というところから、(すくなくとも個人的には)シンプルなオブジェクトをモデルの基本で考えることは(できるのかもしれないけど)拡張性に乏しく難しいと思うし、パターンとするにはあまりよい対応ではない印象です。

このあたりは WPF なんかの MVVM でもそうだし、モデルはモデルとして設計することになると思います。

サンプル

f:id:shikaku_sh:20210301120652p:plain
サンプルコード

個人的にもサンプルをコードに起こしましたが、一応公開しないようにします。

参考