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が
// 反応する)
}
}
こんな感じですね^^