LoginSignup
27
23

More than 5 years have passed since last update.

UnityのScript構成を考えてみる まとめ

Last updated at Posted at 2016-12-30

前説

「ロジックだけをUnityから分離することは可能か。可能だとしてどこまでできるのか」という個人的興味から、UnityのScriptの構成について、サンプルコードを用いて手を動かしながら考察してみた。
本記事はその推移を振り返りをかねてまとめたものである。

過去記事
UnityのScript構成を考えてみる
UnityのScript構成を考えてみる その2
UnityのScript構成を考えてみる その3
UnityのScript構成を考えてみる その4
UnityのScript構成を考えてみる その5

1. View のみ、共通化なし

image.png

まずすべての処理が一クラスに混然と入っている状態からスタートした。あえて共通化を行っていないため(※)、保守性の低さが目に付いた。

(元記事)

※ 実際にこのようなクラスはコピペが多用され共通化があまり進まない傾向がある。

2. LogicとViewの分離

image.png
そこでロジックを分離し、共通化を行いやすくした。

(元記事)

クラス図補注: Configは共通クラス(Utility)のため逐一線を引いていないが、LogicがConfigを利用している。

3. Observerパターン導入によるLogicとViewの疎結合化

image.png
しかしViewクラスが結果を直接受け取る方式であったため、Logicが呼び出し元を意識する必要が残っていた。また、今回は問題とならなかったが、Logic側から更新を発信することも困難だった。
そこでObserverパターンを導入し、LogicとViewの疎結合化を進めるとともにLogic側からイベントを起こすことを可能にした。

(元記事)

実はこの時点ですでにViewクラスはViewModelと呼んだ方が良さそうな状態になっている。値を保持し、ロジックを監視する、表示部分の原本である。
が、後でUniRxを導入したいと思っていたため、この時は触れずにおいた。

4. Logicクラスを切り直す。単一責任原則およびレイヤアーキテクチャを意識して。

image.png
一方、Logicクラス側は切り出したばかりで単一責任原則違反が目立ち、またロジックとデータアクセスが入り混じっていた。このような状態は変更に弱い。
そこで、単一責任原則、およびロジック部分とデータアクセス部分を分けることを意識し、Logicクラスを元にして新しくクラスを切り直した。

(元記事)

5. UniRxを導入し、ViewをPresenterに。

image.png
4までで止めても割と行けると思うが、今回はさらにUniRxを導入してMV(R)Pパターンに組み替えた。生のEventを使う場合と比べて書くのが楽になる他、Rxの概念を利用できるようになるのが主なメリットである。

(元記事)

とはいえ正直かなり大変だったので、やるなら気合を入れてかかったほうがよいと思う。

6. Factoryを利用したレイヤ間依存の疎結合化

image.png
最後にFactoryを使い、抽象に依存するようにしてレイヤ間依存の疎結合化を図った。
後で気が付いたが、Stairwayパターンと呼ばれる状態に近くなっている。

(元記事)

主な目的は
- Model部分を切り出してコードを流用できるようにしたい
- テスタビリティを向上させたい
- 開発中にスタブを使えるようにしたい
といったところである。
が、この手の予定がない場合は導入コストに見合わないためやめたほうがよいと思う。

最終形の説明

最終形について若干説明を加える。
image.png

  • 最終形はMV(R)Pと呼ばれる構成になっている。図の中ではそれぞれVがUnity、(R)PはPresenter、MがNumberMediatorをはじめとする青色の背景色をしたクラスに対応する。最初から絶対にMV(R)Pの形にしようと思って考察を進めたわけではないのだが、表示とロジックの分離、疎結合化、UniRxの導入を行ったら結局こうなった。
  • また、Model部分はビジネスロジック層とデータアクセス層の二つにレイヤを分けている。図で言うとNumberMediatorとNumberがビジネスロジック層、NumberFileがデータアクセス層にあたる。
  • レイヤアーキテクチャの観点で見ると、View層-Presenter層-ビジネスロジック層-データアクセス層の4層構造となる。
  • 図ではFileクラスとなっているが、あるライブラリを導入しようとしたらバグが出たため途中でDataFileと名を変えた。そのためサンプルコードではDataFileとなっている。(ごめんなさい)名前空間をサボらずに使うべきだった。しかもそのライブラリは結局使わなかった。

サンプルコード

利用したサンプルコードはGithubの下記URLにアップした。
https://github.com/nakatatsu/unity-sample

結論

  • 表示とロジックの分離、疎結合化、UniRxの導入を行うと、結局MV(R)Pに行きついた。最初からMV(R)P構成で組んでよさそうである。
    • もちろん別の構成もありえると思うが、結局は似たような構成になる気がする(UniRxを導入しないなら話は別だが)。
  • MV(R)P構成でいうところのModel部分は、Unityからの分離が可能である。
    • UnityEngineとMonoBehaviourの利用を禁止すれば、と前置きがつくが、そう難しいことではないだろう。
  • 一方でPresenterの分離は難しい。
    • MV(R)P構成または類似した構成をとる場合、Modelに書けるコードはなるべくModelに書くようにし、Presenterに書かないほうが、コードの流用やユニットテストの実行を行いやすくなるだろう。
  • ViewはUnityべったりなので分離は無理。

以上。
本記事が何かのお役に立てましたら幸いです。

27
23
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
27
23