MawaLog

一日一日、楽しく生きる。技術と音楽が好き。

Unity::UniRx実装例メモ::ReactiveProperty.Subscribe()ケース別実装例::「普通のint変数の値を条件にUniRxコードでゲーム制御」など

f:id:k_mawa:20180405143952j:plain

コメント

今回のゲーム開発で使った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");
        }

    }
}

こんな感じです^^