UniRxを使ってPhoton CloudのRoomListの更新を監視する

**UniRxについての記事のまとめは[こちら](http://qiita.com/toRisouP/items/48b9fa25df64d3c6a392)**

---
Photon CloudのRoomListの更新をUniRxで通知できるようにしてみました。

##準備
* [【Unity、UniRx、Photon】PUNをRx対応してみた](http://naichilab.blogspot.jp/2014/11/unityunirxphotonpunrx.html)
* [Unityで少しだけ高速なシングルトン(Singleton)](http://tsubakit1.hateblo.jp/entry/20140709/1404915381)

こちらを参考にして、Photonのコールバックを集約して受け付けるPhotonCallbacksというシングルトンオブジェクトを作りました。
このPhotonCallbacksが、Photonのコールバックを全てObservableに変換して提供しくれます。


##部屋のアップデートを通知するObservable

```csharp:RoomListManager.cs
using System.Linq;
using UnityEngine;
using UniRx;

/// <summary>
/// Photonの部屋情報の変更の監視を行う
/// </summary>
public class RoomListManager : TypedMonoBehaviour
{
    private IObservable<RoomInfo[]> _onRoomInfoChangedObservable;

    /// <summary>
    /// 部屋情報が更新された時に新しい部屋リストを提供するObservable
    /// </summary>
    public IObservable<RoomInfo[]> OnOnRoomInfoChangedObservable
    {
        get { return _onRoomInfoChangedObservable; }
    }

    public override void Awake()
    {
        base.Awake();

        //OnReceivedRoomListUpdateのタイミングで最新のRoomList[]を流すストリーム
        _onRoomInfoChangedObservable = PhotonCallbacks.Instance
            //OnReceivedRoomListUpdateが実行された時に発火するObservable
            .OnReceivedRoomListUpdateAsObservable()
            //部屋の更新通知が来たタイミングで最新のRoomInfo[]に差し替える
            .Select(_ => PhotonNetwork.GetRoomList())
            //Hot変換（現在の部屋リストで初期化）
            .Publish(PhotonNetwork.GetRoomList())
            .RefCount();
}
```

**OnRoomInfoChangedObservable**が部屋リストの更新があった時に最新の部屋情報を流してくれるストリームです。
このストリームをSubscribeすれば、部屋情報がアップデートされた時に勝手に最新の状態を取得できるようになります。

##使い方

OnRoomInfoChangedObservableをSubscribeするだけです。
OnReceivedRoomListUpdateのコールバックが来たタイミングで、Subscribe内の処理が実行されます。

```csharp:RoomListView.cs
using UniRx;
using UnityEngine;
using UnityEngine.UI;

public class RoomListView : MonoBehaviour
{
    [SerializeField] 
    private RoomListManager _roomListManager;
    
    private void Start()
    {
        //部屋情報が更新された時に現在の部屋数をコンソールに表示する
        _roomListManager
            .OnRoomInfoChangedObservable
            .Subscribe(x =>
            {
                Debug.Log(string.Format("現在の部屋数:{0}", x.Length));
            });
    }
}
```

今回はただDebug.Logで部屋の数を表示しているだけの処理内容です。
このSubscribeの中身でGUIの表示変更をやると良いかと思います。

###余談

HotとColdの特性はしっかり把握しておかないと意図しない挙動するので注意した方が良いです。

参考: [RxのHotとColdについて](http://qiita.com/toRisouP/items/f6088963037bfda658d3)

#追記(2015/04/07)

ReactivePropertyというものがUniRxに追加されたので、こちらを使ったほうがよりシンプルに書けます

```csharp:PhotonRoomListModel.cs
public class PhotonRoomListModel : MonoBehaviour
{
    public ReactiveProperty<RoomInfo[]> RoomInfoReactiveProperty
     = new ReactiveProperty<RoomInfo[]>(new RoomInfo[0]);

    private void OnReceivedRoomListUpdate()
    {
        _reactiveRooms.Value = PhotonNetwork.GetRoomList();
    }
}
```

```csharp:RoomsUpdateObserver.cs
public class RoomsUpdateObserver : MonoBehaviour
{
    [SerializeField]
    private PhotonRoomListModel roomModel;

    void Start()
    {
        roomModel
            .RoomInfoReactiveProperty
            .AsObservable()
            .Subscribe(rooms =>
                {
                    Debug.Log(rooms.length);
                });
    }
}
```