MRが楽しい

MRやVRについて学習したことを書き残す

ReactiveCollectionでコレクションの追加と更新の変更をまとめて通知する

本日は UniRx の小ネタ枠です。
ReactiveCollection でコレクションの追加と更新の変更をまとめて通知する方法について記事にします。

前回記事

以下の前回記事の続きです。
bluebirdofoz.hatenablog.com

Merge

Merge オペレータを利用することで複数のシーケンスをまとめた Observable を作成できます。
今回は Select オペレータで追加時と更新時のフォーマットを同じにして、Merge で1つのシーケンスにまとめて通知を行ってみます。

サンプルスクリプト

以下のサンプルスクリプトを作成してみました。
コレクションの追加、更新のシーケンスをまとめた Observable を購読してデバッグログを出力しています。
・ReactivePropertyTest4.cs

using System;
using Cysharp.Threading.Tasks;
using UniRx;
using UnityEngine;

public class ReactivePropertyTest4 : MonoBehaviour
{
    private readonly ReactiveCollection<string> dataProp = new();

    private IObservable<(int Index, string Value)> CustomObservable =>
        dataProp.ObserveAdd() // コレクション追加時の通知
        .Select(data => (data.Index, data.Value)) // データフォーマットを(int, string)に変換
        .Merge( // 複数のシーケンスをまとめる
            dataProp.ObserveReplace() // コレクション更新時の通知
            .Select(data => (data.Index, Value: data.NewValue))) // データフォーマットを追加時と同じ(int, string)に変換
        .Select(data => (data.Index, data.Value)); // 最終的なフォーマット変換(必要であれば)

    void Start()
    {
        // コレクション追加時と更新時を合わせて通知
        CustomObservable
            .Subscribe(data =>
            {
                Debug.Log($"Add or Replace : Index = {data.Index}, Value = {data.Value}");
            })
            .AddTo(this);

        // 追加
        dataProp.Add("First");
        dataProp.Add("Second");
        dataProp.Add("Third");
        
        // 更新
        dataProp[2] = "End";
        
        // 削除
        dataProp.Remove("Second");

        // クリア
        dataProp.Clear();
    }
}

以下の通り、コレクションの追加時と更新時のログを1つの Observable を使って出力することができました。