Unity::UniRx実装例メモ::ObserveEveryValueChanged()のゲームにおけるケース別実装例::「スコアが加点されたら加点状況に応じてUIに反映&効果音再生」など
コメント
今回のゲーム開発で使ったUniRxの実装例をメモしておこうと思います。ゲームで定義した値に変化があったら実行ではObserveEveryValueChanged()を使うと直観的にも挙動が分かりやすい実装になった!今回の例は、UniRxで、「敵を倒して加点したら、点数変動を察知して、スコアTextに反映」と、「体力が最初10だけど0になったらゲームオーバーシーンへ移動」の実装例をご紹介します。事例としては応用かけやすいかなと・・・^^
参考資料
大変参考になりました!^^ ありがとうございます!
実際の実装後の動き
下記の実装例コードはこの自分で作ったゲームで実際に動いています^^「敵を倒して加点したら、点数変動を察知して、スコアTextに反映」と、「体力が最初10だけど0になったらゲームオーバーシーンへ移動」がUniRxで実装しています。
コード解説::ReactivePropertyの値の監視が2つ以上のスクリプトにまたがる場合(汎用性高い)
この実装は「敵を倒して加点したら、点数変動を察知して、スコアTextに反映」の部分です。
//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; //の代わりに設定するゲームスコアの値 //スコア加点時に再生する音声のセッティング private AudioSource audioSource_hit; public AudioClip sound_hit; [SerializeField] private Text _text;//スコア表示する変数欄 void Start () { //1行目:rp_gameScoreの値に変化があったら、 //(※ReactiveProperty<int>の値は.Valueで取り出す) //2行目:.SubscribeToText(_text)=>_textに値を流す rp_gameScore.ObserveEveryValueChanged(_ => _.Value) .SubscribeToText(_text); //1行目:rp_gameScoreの値に変化があったら、 //2行目:得点が1点以上の場合のみ.Subscribeに流す(0点も含めるとゲームスタート時に1度音が再生されてしまうのを防ぐ) //3行目:スコア加点時の音声ファイル再生 rp_gameScore.ObserveEveryValueChanged(_ => _.Value) .Where(_ => _ > 0) .Subscribe(_ => audioSource_hit.Play()); }
↓
//値が変化する関数を記述したスクリプト using UniRx; void OnCollisionEnter(Collision other) { if (other.gameObject.tag == "Ghost") { //衝突したら、ReactiveProperty<int>の //オブジェクトの値を変化させる(加点) //(変化があった時点で // すべての監視設定済みSubscribeが発火) GameMasterScript.rp_gameScore.Value += 1; } }
コード解説::ReactivePropertyの値の監視が1つのスクリプトで完結する場合(汎用性低め)
この実装は「体力が最初10だけど0になったらゲームオーバーシーンへ移動」の部分です。
//ひとつのスクリプト内で完結するタイプの書き方 using UniRx; using UniRx.Triggers; //いらんかも using UnityEngine.UI; using UnityEngine.SceneManagement; public class ColliisionController : MonoBehaviour { ReactiveProperty<int> score = new ReactiveProperty<int>(10); //↑要するに、scoreは、HPscoreとしてint変数と同じ使い方で //ReactiveExtention<int>を設定する //public staticはつけないから他のスクリプトで //参照できない(参照させたかったらpublic staticつける) // Use this for initialization void Start() { //1行目:scoreの値に変化があったら、 //(※ReactiveProperty<int>の値は.Valueで取り出す) //2行目:scoreが0以下のとき(HPが0になったら) //3行目:"Ending"シーンへ移動 score.ObserveEveryValueChanged(_ => _.Value) .Where(_ => _ <= 0) .Subscribe(_ => SceneManager.LoadScene("Ending")); } // Update is called once per frame void Update() { } void OnCollisionEnter(Collision other) { if (other.gameObject.tag == "Ghost") { score.Value -= 1; //HPscoreをー1する。 //(これにより、ObserveEveryValueChangedが // 反応する) } }
こんな感じですね^^