UniRxのReactivePropertyを用いたMV(R)Pパターンを学習しました
UniRxのReactivePropertyを用いたMV(R)Pパターンを勉強しました. Unity1Weekの後半でコードのぐちゃぐちゃ具合で痛い目に遭ったので, これを機にしっかり設計,責務配置を考慮したコーディングの勉強をやっていきます.
UniRx・ReactiveProperty
こちらのqiita記事シリーズを読んでいきました. qiita.com
今日はその1からその3の途中まで読みました.
UniRx入門 その1 - Qiita
UniRx入門 その2 - メッセージの種類/ストリームの寿命 - Qiita
UniRx入門 その3 -ストリームソースの作り方 - Qiita
Observerパターンやストリームの概念はは以前学習したことがあるのでスムーズに頭が入った. Subject,IObservable,IObserver,Subscribe… Observerパターン[Java] - デニッキ ラムダ式とStreamAPI[Java] - デニッキ
その3の途中でReactivePropertyの項でMV(R)Pパターンの話が出てきたので,やってみた.
MV(R)Pパターン
Javaを触れる際にMVCパターンを学習したことがありました. MVCとMVPの違いとかは以下の記事がわかりやすく説明されてる.
Webアプリケーション開発者から見た、MVCとMVP、そしてMVVMの違い - Qiita
サイバーエージェントブログのこちらの記事もわかりやすい.
Web出身のUnityエンジニアによる大規模ゲームの基盤設計 | CyberAgent Developers Blog
MV(R)PパターンはModel View (Reactive) Presenterパターンのこと.Reactiveが加わっている. とりすーぷさんのこちらのスライドも参考にしました.
www.slideshare.netUnity1weekでuGUI実装する際のコードもなんじゃこりゃ~になってたので
これはしっかり勉強しておきたい.
ちなみにUnity1weekで用いたライフ表示のアセットはMVPパターンだったのを思い出した. でもHealthBarController.csって書いてあったからMVCパターンなのかなあ.難しい. assetstore.unity.com 具体的なコード部分は各自がアセットダウンロードして確認して頂ければ.
ReactivePropertyを用いたMV(R)PパターンでuGUI実装してみた
こちらの記事が参考になったので利用いたしました.
Unityで学ぶMVPパターン ~ UniRxを使って体力Barを作成する ~ - Qiita
Unityで学ぶMVPパターン(2) ~ Viewコンポーネントを複数にする ~ - Qiita
このサンプルコードをできる限りカプセル化とDisposeをさせ,
さらにプレイヤーがダメージを受ける際にHPを減らすのを加えて実装しました.
こんな感じ. Model部分
using System.Collections; using System.Collections.Generic; using UnityEngine; using UniRx; public class StatusModel : MonoBehaviour { private int healthMax = 100; private ReactiveProperty<int> healthRP = new ReactiveProperty<int>(100); public IReadOnlyReactiveProperty<int> Health { get { return healthRP; } } public int HealthMax { get { return healthMax; } } public void GetDamaged(int value) { if (healthRP.Value > 0) { healthRP.Value -= value; } else { healthRP.Value = 0; } } }
Presenter部分 今回プレゼンターは1View1Presenterではなく,一纏めにしています.
using System.Collections; using System.Collections.Generic; using UnityEngine; using UniRx; public class ParameterPresenter : MonoBehaviour { [SerializeField] private StatusModel model = null; [SerializeField] private ParameterViewBase[] healthViews = null; void Awake() { foreach (var view in healthViews) { model.Health .Subscribe(value => { view.SetParameter(model.HealthMax, value); }) .AddTo(this); } } }
View部分 qiita記事と殆ど変わりません. publicフィールドになっていたのをprivate serializefieldに変えただけです.
敵の攻撃部分 ボタンクリック時の挙動をObservable化した.
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UniRx; [RequireComponent(typeof(Button))] public class Enemy : MonoBehaviour { [SerializeField] private StatusModel model = null; [SerializeField] private int damage = 5; void Start() { Button button = GetComponent<Button>(); button.OnClickAsObservable() .Subscribe((_) => { model.GetDamaged(damage); }) .AddTo(this); } }
やってみた
Enemy Attack ボタンを押すごとにPlayer Healthが減っていきます. 減るごとに回りが赤く,ヘルスバーも,テキストも減っていきます.
終わりに
PS. 何か気になる部分とかツッコミ部分があればコメントくださいです.