前提
- ViewとModelは、MVPのViewとModelのイメージ
- 以下は自分の認識
UnityにおけるViewとは
ViewというとGUI、画面を想像しがちだが、ViewとはUI、ユーザーインターフェイスである。ユーザーとの境界面の入出力全般を指す。
そしてUnityの持つ主な機能のほとんどはユーザーインターフェイスを担当するものである。
引用元:https://commons.wikimedia.org/wiki/File:Linux_kernel_INPUT_OUPUT_evdev_gem_USB_framebuffer.svg
人とソフトウェアの間にはハードウェアが存在し、ハードウェアと通信することでシステムが成り立つ。 入力には、キーボードやマウス、コントローラー、タッチ、ジェスチャー、マイクなどが含まれ、出力には、グラフィックス、オーディオ、デバイスに直接信号を送って様々な効果を起こすなどが含まれる。
引用元:https://gamyguru.wordpress.com/2012/07/16/inside-the-game-general-game-structure/
ゲームエンジンを構成するのは、主にグラフィック、サウンド、物理演算、入力制御である。
Unityのマニュアルから主要な項目を抜粋すると以下のようになる。
- 入力
- 2D、3D
- グラフィックス
- 物理演算
- ネットワーク
- オーディオ
- アニメーション
2D、3D、アニメーションはグラフィックに含まれるし、ネットワークは補助機能として組み込まれている。これらはほぼゲームエンジンの構成と一致する。
これはゲームエンジンおよびUnityが持つ主な機能のほとんどがユーザーインターフェイスを担当するものであることを物語っている。
Viewはユーザーインターフェイスなので、Unityが持つユーザーインターフェイスの機能を操作する処理はViewとして実装するのが望ましいと言える。
引用元:https://blog.tai2.net/the_clean_architecture.html
みんな大好きClean Architecture。(個人的にはまったく推してませんが)
この絵と照らし合わせてみると、Dveicesあたりが入力で、UIおよびDevicesあたりが出力だろうか。 そしてUnityはFrameworkでもある。
一番外のレイヤーにおいてハードウェアとのつなぎやそこでの整合性を調整する処理はやはりそのレイヤーが受け持つべきだろう。
ビューロジック貧血症
マーチン・ファウラーが名付けたドメインモデル貧血症という概念がある。
簡単に言うと、ドメインレイヤに位置するのに「単にプロパティを持っただけのデータクラス」を指す。
何が問題かというと、集約すべき振る舞いが集約されていないこと。使う側が振る舞いを決めてしまうのでドメインモデルとしては中身がない。ドメインモデル貧血症とは、単なる手続き型設計とも言える。
ドメインモデルはオブジェクト指向設計を基本とするものであるが、このアンチパターンは、真逆のデータと操作が分離されるデータ指向設計になっているという話である。
原典の詳細は置いておいて、ここでは「必要な処理が集約されていない」という意味で例としてあげた。
前述した通り、Unityが持つユーザーインターフェイスの機能を操作する処理はViewの範疇である。
Viewの定義があやふやなままだと、Viewの処理をModelに書いてしまうことがある。
そうするとModel層でMonoBehaviourや必要以上にUnityの機能を参照することになる。
極端な場合、ViewはUnityとPresenterの間でEventを発行して、結果を反映するだけの薄っぺらな層になる。
Viewの中で集約して完結すべき処理が外に漏れ出ているということになる。
モデル肥満
主にWebシステムなどで揉まれた設計思想であるDDDやClean Architecture、またはMVPも含まれることもあるが、Modelやドメインに注目した時にどうしてもそこを大きくしたい作用のようなものが働く。
特にUnityの場合、先に説明したようにほとんどがユーザーインターフェイスを担当する機能であるため、Modelが想像よりも薄くなってしまうことが多い。
でもそれは仕方がないことだしそれが正しい。過剰にModelを膨らます必要はない。
ジャンルによって変わるモデルの厚さと位置
ゲームの主なジャンルをいくつかあげてみる。
- アクション
- シューティング
- ロールプレイング
- シミュレーション
- パズル
アクションやシューティングなどは、Viewつまりユーザーインターフェイスがありきなゲームである。グラフィックや物理演算、入力方法などが変われば仕様から何から考え直さないと成立しなくなる。入力から出力までの距離が近すぎるのだ。
一方でロールプレイングやシミュレーションなどは、切り離せる可能性がある。ターン制のものなど入力を待つタイプが馴染みやすい。ゲーム以外のWebシステムと近いループが生まれるからだ。 Webシステムで作り直した時にゲームが成り立つかどうかを想像すると判断しやすい。
つまり、ジャンルやゲームの性質によってはViewとドメインが切っては切り離せない関係になる。
ドメインではない処理の一部を切り離してModelと呼ぶことはできなくはない。
また、ソシャゲではインゲーム、アウトゲームと呼ばれる分け方があるが、前者はインゲーム、後者はアウトゲームが近いだろう。
アクションなどは、Modelがないかもしれないしあっても薄い。そしてViewに近い。
ロールプレイングなどは、Modelを厚くできるしPresenterで距離を保つこともできるようになる。
世界の時間
インゲーム、アウトゲームで話すが前述のジャンルも然りだ。ゲーム以外のシステムはアウトゲームと考えていいだろう。
インゲーム、アウトゲームを別けた場合、インゲームは「世界時間が止まらない世界」、アウトゲームは「世界時間が静止する世界」である。静止する世界にも一部サウンドやアニメーションなどあるが、ローカル時間が流れてたり、ループしていたりするだけだ。
アウトゲームはユーザーの入力によって時間が動き出し、結果を出力することでまた時間が静止する。
インゲームはユーザーの入力の有無に関係なく常に動く。ユーザーの入力は「動いている世界に干渉するイベントを発生させる」と捉えることがでる。
そもそもゲームエンジンは「世界の時間を動かし続ける」フレームワークだ。
ゲーム以外のアプリケーション(スマホでもPCでも)や、Webアプリケーションは、基本的にイベント駆動型アプリケーションであり、全く性質が異なる。
ゲーム以外から入ってきた設計思想はつまり「時間が静止する世界」で設計する手法なのだ。
使い所もあるし使えないところもある。合う要素もあれば合わない要素もある。