R3とは
C#のUniRxの後継として開発されたライブラリです。時間軸に沿ったデータの変化を効率的に処理できます。UnityのUpdate処理は負荷のかかる処理のため、uGUIの表示更新などにはこちらを使用していました。
導入方法
導入方法にはいくつかありますので先ほどのURLを参考にするといいでしょう。
- Package Managerを開く
- 環境設定を開く
- 名前、URL、Scope(s)を入力する
- Package ManagerのマイレジストリにOpenUPMとUnityNuGetが表示されるので、R3を検索して、R3とR3(NuGet)をインストールする
(通常は「R3」のみをインストールすれば十分です)
R3の適切な使いどころ例
- アクションゲームで一定の距離内で敵が攻撃を始める処理もありますが、あくまでR3は処理の可読性向上が目的のため、Update処理で行った方が軽いという場合もある
- 単純なボタン入力だけならR3を使う必要ない
- また入力はInput Systemで行う方が多いので、それ以外のゲーム状態の監視、オブジェクト間の関係性のチェックに使う
基本的な概念
Observable(観測可能なもの)
データやイベントの流れを表現するオブジェクトです。これを発行することで時間軸での処理が可能になります。
Observer(観測者)
Observableから発行されるデータを受け取って処理をするオブジェクトです。
Subscribe(購読)
ObserverがObservableからデータを受け取るための仕組みです。
以下はボタンを押したときにログに表示するコードです。
using UnityEngine;
using R3;
using UnityEngine.UI;
public class R3Test1 : MonoBehaviour
{
[SerializeField] private Button _button;
void Start()
{
//Observable
_button.OnClickAsObservable()
//Subscribe
.Subscribe(
//Observer
_ => Debug.Log("Click")
).AddTo(this);
}
}
R3の基本操作
ここに載せるもの以外にも使用方法は多岐にわたりますが、ゲームでよく使用されるものをここに載せていきます。
Timer
経過時間で処理を実行することができます。アイテムを取得したら、パワーアップ効果を5秒適用したり、敵を倒してから3秒後に次の敵をスポーンさせるといった処理ができます。
以下は3秒経過したらログを表示します。
using System; // TimeSpan使用のために必要
Observable.Timer(TimeSpan.FromSeconds(3))
.Subscribe(_ => Debug.Log("3秒経過"))
.AddTo(this);
以下は敵を倒してから3秒後に敵をスポーンさせる処理です。
private void OnEnemyDefeated()
{
Debug.Log("敵を倒した");
Observable.Timer(TimeSpan.FromSeconds(3))
.Subscribe(_ => SpawnEnemy())
.AddTo(this);
}
Where
条件フィルタをかけて実行する処理です。HPが一定以下になったらUIを更新する、プレイヤーが特定のエリアに入ったら処理をするなどに使えます。
以下はプレイヤーのHPが0以下になったときだけ実行する処理です。
Observable.EveryUpdate()
.Where(_ => playerHP <= 0) .Take(1) .Subscribe(_ => Debug.Log("ゲームオーバー"))
.AddTo(this);
AddTo
オブジェクトが破棄されたときなどにR3で定期実行している処理を破棄する処理です。これがないとオブジェクトが破棄されても処理が継続してしまいます。
まとめ
UniRxをメインで使っていたので後継のR3をそろそろ使おうと思いまとめてみました。ゲームの設計の段階でデータと画面表示の部分で処理を分けた方が処理として簡潔で見やすく、バグも起きにくいので使用していましたが、その他にも利用はできるのでこちらで少しずつまとめていこうと思います。