MRが楽しい

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

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

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

前回記事

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

Merge

Merge オペレータを利用することで複数のシーケンスをまとめたObservableを作成できます。
今回はObservable.Mergeを使って様々な変更通知を1つのシーケンスにまとめたObservableを作ります。

サンプルスクリプト

以下のサンプルスクリプトを作成してみました。
コレクションの追加、更新、削除、移動、クリアの通知をまとめたObservableを購読してデバッグログを出力します。
・ReactivePropertyTest5.cs

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

public class ReactivePropertyTest5 : MonoBehaviour
{
    // コレクションの変更のタイプ
    private enum ChangeType
    {
        Add,
        Remove,
        Replace,
        Move,
        Reset,
    }
    
    // ReactiveCollectionを使って、コレクションの変更を監視する
    private readonly ReactiveCollection<string> dataProp = new();

    // ReactiveCollectionの様々な変更を一括監視するObservable
    private IObservable<(ChangeType, string[])> DataPropObservable => Observable.Merge(
        dataProp.ObserveAdd().Select(_ => (ChangeType.Add, dataProp.ToArray())),
        dataProp.ObserveRemove().Select(_ => (ChangeType.Remove, dataProp.ToArray())),
        dataProp.ObserveReplace().Select(_ => (ChangeType.Replace, dataProp.ToArray())),
        dataProp.ObserveMove().Select(_ => (ChangeType.Move, dataProp.ToArray())),
        dataProp.ObserveReset().Select(_ => (ChangeType.Reset, dataProp.ToArray()))
    );

    void Start()
    {
        // コレクションの変更時に、変更のタイプと変更後のリストの内容を通知する
        DataPropObservable
            .Subscribe(data =>
            {
                Debug.Log($"ChangeType : {data.Item1}, Data : {string.Join(", ", data.Item2)}");
            })
            .AddTo(this);

        // 追加
        dataProp.Add("First");
        dataProp.Add("Second");
        dataProp.Add("Third");
        
        // 更新
        dataProp[2] = "End";
        
        // 削除
        dataProp.Remove("Second");
        
        // 移動
        dataProp.Move(0, 1);

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

以下の通り、コレクションの変更を1つの Observable を使って監視して出力することができました。