【Unity】次世代のUniRx「R3」を導入してみる
Unity 2022.3.16
R3 0.1.2
はじめに
2024年1月9日、Cysharp社からR3というライブラリがプレビュー公開されました。
github.com新しいC#用のRxをプレビューリリースしました!dotnet/reactiveとUniRxの進化系を目指して、抜本的なAPIの見直しと、現代の技術での再実装による飛躍的なパフォーマンス向上、そしてプラットフォーム抽象化により、WPF, Unity, AvaloniaそしてGodotに対応しました!https://t.co/McU0VSOyRk
— neuecc (@neuecc) 2024年1月9日
UnityでReactive Extensions(Rx)を実現するライブラリとしては既にUniRxがありました。UniRxもCysharp社の代表を務められているneueccさんがリリースされているライブラリになっています。
github.com
ただ、最新版である7.1.0のリリースは2020年2月26日とほぼ4年前でそれ以降新機能の追加やUnity・C#の更新に伴うパフォーマンス向上のアップデートは行われておらず、個人的にはUniRxの更新ないしRxの実現を図るハイパフォーマンスなライブラリの登場は待ち望んでいたところでした。R3自体はUnityでの使用に限定されたものではなく、UniRxとの完全な互換性があるわけでもありませんが、Unityに統合するためのパッケージも同時に提供されておりUnityを使用する上ではUniRxの進化版ライブラリといえそうです。
具体的に自分が更新を望んでいた機能の例として、AddTo
という拡張メソッドの存在があります。AddTo
メソッドはIDisposable
に対する拡張メソッドの形で定義されており、ストリームの購読破棄をゲームオブジェクトの破棄タイミングに紐づけて行えるという非常に便利な機能を提供してくれます。以下のサンプルコードはかなり恣意的なものですが、AddTo
メソッドを用いることでsampleStaticSubject
に対して購読と購読破棄をメソッドチェーンの形で記述できています。
using UniRx; using UnityEngine; public sealed class AddToTest : MonoBehaviour { private static readonly Subject<Unit> sampleStaticSubject = new(); private void Start() { sampleStaticSubject // 購読 .Subscribe(_ => Debug.Log("Test")) // 購読破棄をゲームオブジェクトの破棄と同時に行う .AddTo(this); sampleStaticSubject.OnNext(Unit.Default); } }
一方でこのAddTo
メソッドを使用すると、実行時にゲームオブジェクトに対してObservableDestroyTrigger
という購読しているストリームを管理するためのコンポーネントが自動的にアタッチされます。
これは従来のUnityの仕組み上このような形で実装せざるを得なかったと思いますが、できればゲームオブジェクトに余計にコンポーネントを増やすことは避けたいところです。しかしUnity 2022.2からMonoBehaviourにdestroyCancellationToken
というCancellationToken
型のプロパティが追加され、これを用いることでコンポーネントを増やすことなく購読の寿命の紐付けが簡易かつハイパフォーマンスに行えるようになりました。(非同期処理の文脈においてですが、以下のUnity公式の動画でdestroyCancellationToken
について軽く触れられています。)
新しいR3ではここについても現代化が図られています。先ほどのサンプルと同様のコードをR3を使って書くとこんな感じになります。
using R3; using UnityEngine; public sealed class AddToTest : MonoBehaviour { private static readonly Subject<Unit> sampleStaticSubject = new(); private void Start() { sampleStaticSubject // 購読 .Subscribe(_ => Debug.Log("Test")) // 購読破棄をゲームオブジェクトの破棄と同時に行う .AddTo(this); sampleStaticSubject.OnNext(Unit.Default); } }
実際、using UniRx;
がusing R3;
に書き換わっただけで他の部分は完全に同じです。ですがR3の方のAddTo
は以下のように内部的にdestroyCancellationToken
に対する紐付けをする実装に変わっており、管理用のコンポーネントがアタッチされたりすることはないコスパの良いものになっています。
public static CancellationTokenRegistration AddTo(this IDisposable disposable, MonoBehaviour value) { return disposable.AddTo(value.destroyCancellationToken); }
上記であげた例は非常に表層的なもので、実際には抜本的な設計の変更や大幅なパフォーマンス向上、ストリームの購読状況が可視化できるTracker Windowの付属など聞いただけでわくわくするような機能が多く盛りこまれているライブラリになっています。R3のGitHubリポジトリにあるREADMEには詳細についてまとめられているため、そちらを読めば大体の内容がわかると思います。R3の具体的な進化点については調査中のところもあるので、また別記事にまとめさせていただきたいと思います。
R3はUniRxと導入方法(配布形式)が変わっているため、この記事ではUnityにR3を導入するところまでを行ってみます。
注意
R3はプレビュー段階のライブラリです。バグが含まれていたりAPIが大きく変更されたりする可能性が十分にあるので、プロジェクトに導入する際はバックアップを取るなどの準備を行ってからにした方が良いでしょう。
インストール
R3はNuGetパッケージとして配布されています。
ここから直接dllをダウンロードしてくるのも良いのですがアップデートが面倒だったり依存しているパッケージもあったりするので、今回はR3のREADMEで紹介されているようなNuGetForUnityを使ったインストール方法にします。
NuGetForUnityのインストール
NuGetForUnityはNuGetのパッケージをUnityへ簡単に導入することができるようにするライブラリです。
この記事ではOpenUPM経由でインストールしますが、git urlでも問題なく入れることができます。
Project SettingsからPackage Managerのタブを開き、Scoped Registryとして以下のように入力し、Applyを押します。
Name | OpenUPM(任意の名前) |
URL | https://package.openupm.com |
Scope(s) | com.github-glitchenzo.nugetforunity |
これでPackage Managerの選択肢にMy Registriesが追加されます。その後Window/Package Manager
からPackage Managerを開きMy Registriesを選択、表示されているNuGetForUnityをインストールします。
R3(コア部分)のインストール
次にR3のコア部分をインストールします。NuGetForUnityのインストールが成功していればUnityのツールバーにNuGetの表示が増えているはずなので、そこからManage NuGet Packagesを開き検索バーに入力されているSearchの文字をR3に置き換えてSearchを押します。余談ですが、NuGetForUnityを使う際プレースホルダとしてのSearchの文字がラベルではなく実際に入力されている文字なのがいつも気になります。 表示された中からR3 by Cysharpとなっているパッケージを見つけ、インストールします。2024年1月11日現在のバージョンは0.1.2のようです。
R3(Unity統合部分)のインストール
最後にR3のUnityに対する機能を提供する部分をインストールします。まだOpenUPMでの提供は行われていないため(プレビュー版ということもあり今後提供されるかも不明です)、git url経由でインストールします。またWindow/Package Manager
を開き、Add package from git URL...を選択して出た入力欄にhttps://github.com/Cysharp/R3.git?path=src/R3.Unity/Assets/R3.Unity
と入力してAddします。
これでR3のUnity統合部分もインストールされ、使用する準備が整いました。