ReactivePropertyとは
値の変化を自動で監視できる変数のこと。通常の変数と異なり、値が変わった時に自動的に処理を実行することができます。
通常HPをUIに表示する場合、Update関数で毎フレームHPのステータス状態を監視して処理をするが、これだと負荷のかかる処理になるため、ReactivePropertyを使用すると常時監視をする必要がないというメリットがあります。
また、データを管理する処理と画面上に表示する処理を分けて記述できるメリットがあり、処理の流れを追いやすく管理しやすいです。
ReactivePropertyの例
以下はHPをボタンを押して0になったらゲームオーバーと表示する処理です。
HPを管理する処理と、UIを管理する処理を分けることによって、処理の見通しが良くなりますね。
処理の流れとしては、ReactivePropertyでCurrentHPという変数を用意し、購読する側の処理でこのCurrentHPをStartでSubscribeすることによって購読できるようにします。その後は以前までの記事の通りに、WhereなどのOperatorでフィルタリングして条件を設定することができます。
また、ReactivePropertyの変数を参照する場合は、変数名の後に.Valueを付ける必要があります。

//ReactivePropertyで体力を管理する処理
using UnityEngine;
using R3;
public class ReactiveProperty1 : MonoBehaviour
{
public ReactiveProperty CurrentHP = new(10);
public void TakeDamage(int damage)
{
CurrentHP.Value -= damage;
}
}
//体力の処理を購読して、体力に変化があった場合にUIの表示を切りかえる処理。
using UnityEngine;
using R3;
using UnityEngine.UI;
using TMPro;
public class ReactiveProperty2 : MonoBehaviour
{
[SerializeField] private TextMeshProUGUI hpText;
[SerializeField] private ReactiveProperty1 reactiveProperty1;
[SerializeField] private Button damageButton;
private void Awake()
{
damageButton.onClick.AddListener(Damage);
}
void Start()
{
reactiveProperty1.CurrentHP
.Subscribe(hp =>
{
hpText.text = "HP:" + hp.ToString();
if (hp <= 0)
{
hpText.text = "Game Over";
}
})
.AddTo(this);
}
public void Damage()
{
reactiveProperty1.TakeDamage(1);
}
}
その他の実装方法
シングルトンで参照することもできるが、複数の箇所でデータを参照する場合、どこから取得したのかシングルトンだと把握しにくくなるため、基本的にはSerializeFieldで参照する方がよいですね。
DIというパターンもあるが、チーム開発や大規模なゲームで使用されることが多いため、個人開発レベルではあまり使わないかもしれないが、いずれ挑戦してみたいですね。
まとめ
簡単な例でReactivePropertyの使い方を書いてみました。アクションゲームでも得点や体力などの変数を管理することが多くありますが、Updateで毎フレーム管理するのは可読性の面で、処理の流れを追うのに少し分かりにくさがあるため、ReactivePropertyを使って処理を分けてみると良いですね。
次回はイベント処理に使用できるSubjectについて書いていきます。