Unity::UniRx実装例メモ::ReactiveProperty.Subscribe()ケース別実装例::「普通のint変数の値を条件にUniRxコードでゲーム制御」など
コメント
今回のゲーム開発で使ったUniRxの実装例をメモしておこうと思います。ReactiveProPertyの使いこなしはUniRxでの実装実現の大きな一歩になるし、とにかく便利で読みやすいコードになるので、大プッシュしておきたいと思います^^ .Subscribe()はどういうときに使うのかわかりやすい記事を目指しました。
今回の例は、UniRxで、「単にint変数として活用できるようなReactivePropertyを単にテキスト表示してみる」と、「複数のスクリプトでひとつの変数(的オブジェクトのReactiveProperty)を参照し別々の出力をさせる(Subscribe)」と「普通のint変数の値によって条件づけをして、一定条件のときにのみReactivePropertyを発火させる」の実装例をご紹介します。
実際の実装後の動き
下記の実装例コードはこの自分で作ったゲームで実際に動いています^^「体力Scoreの表示」「エンディングシーン(変数定義したスクリプトのあるシーンとは別のシーン)でスコア表示」「タイマーが0になったらエンディングシーンへ遷移」がUniRxで実装しています。
コード解説::ReactivePropertyを条件づけしないでSubscribeだけ発火させる
この実装は「体力Scoreの表示」の部分です。
using UniRx; using UniRx.Triggers; using UnityEngine.UI; public class ColliisionController : MonoBehaviour { //スコア表示させる部分 [SerializeField] private Text _text; //オプションつきのpivate int =10;と //同じようなものだと思えば理解しやすい ReactiveProperty<int> score = new ReactiveProperty<int>(10); // Use this for initialization void Start() { //.ToString()で文字列にして挿入 //_text.textで流し込める //(_textではないところに注意) score.Subscribe(x => _text.text = x.ToString()).AddTo(this);
コード解説::ほかのスクリプトのReactivePropertyを参照してSubscribe発火を実装
この実装は「エンディングシーン(変数定義したスクリプトのあるシーンとは別のシーン)でスコア表示」の部分です。
//ReactiveProperty<T>を設定したスクリプト using UniRx; using UniRx.Triggers; //いらないかも using UnityEngine.UI; public class GameMasterScript : MonoBehaviour { public static ReactiveProperty<int> rp_gameScore = new ReactiveProperty<int>(0); //↑要するに、public static int gameScore = 0; //の代わりに設定するゲームスコアの値
↓
//Subscribeを発火させたい別のスクリプト@別シーンにアタッチしたもの //スコア表示させる部分 [SerializeField] private Text _text; // Use this for initialization void Start () { //[スクリプト名(クラス名)].[変数名].Subscribe()で //呼び出せる GameMasterScript.rp_gameScore .SubscribeToText(_text); //↑そのまま値を文字列として流し込むメソッド }
コード解説::Obserbableではない変数を条件にして、Subscribe発火させる
この実装は「タイマーが0になったらエンディングシーンへ遷移」の部分です。
using UniRx; using UniRx.Triggers; //↑※UpdateAsObservable()をつかうときは必要! using UnityEngine.UI; using UnityEngine.SceneManagement; public class TimerController : MonoBehaviour { public Text Timer;//タイマー public static float Timer_sec = 120.0f; //タイマーの持ち時間 void Start () { //1行目:Update()と同じ感じの毎フレーム更新時作動 //だけど、ReactiveExtention機能つきの //Upadate()みたいなもの //2行目:Timer_sec(普通のfloat変数)<=0で //時間切れになったら //3行目:Endingシーンをロード this.UpdateAsObservable() .Where(_ => Timer_sec <= 0) .Subscribe(_=>SceneManager.LoadScene("Ending")); } // Update is called once per frame void Update () { // 下記は普通のC#によるタイマーの設定、 //0秒を下回ったら持ち時間マイナスになると変なので //0に固定する if (Timer_sec >= 0) { Timer.text = Timer_sec.ToString("N2"); Timer_sec -= Time.deltaTime; } if (Timer_sec < 0) { Timer_sec = 0; Timer.text = Timer_sec.ToString("N0"); } } }
こんな感じです^^