1. 程式人生 > >UniRx第一季學習(六) ------ ObservableWWW/ReactiveCommand /ReactiveCollection/ ReactiveDictionary/AsyncOper

UniRx第一季學習(六) ------ ObservableWWW/ReactiveCommand /ReactiveCollection/ ReactiveDictionary/AsyncOper

課程地址 : http://www.sikiedu.com/course/271

涼鞋大大的,可以的話大家多支援一波~


一.ObservableWWW優雅的⽹絡請求操作

以往我們不管使⽤ WWW 還是 UnityWebRequest 都要使⽤ Coroutine 去驅動。但是使⽤協程寫出來的程式碼,需要⼀堆判斷,導致程式碼⾮常混亂。

void Start()
        {
            ObservableWWW.Get("http://sikiedu.com")
                         .Subscribe(responseText =>
                         {
                             Debug.Log(responseText);
                         }, e =>
                         {
                             Debug.LogError(e);
                         });
        }

除了 Get 也⽀持了 Post,還有 GetWWW 和 PostWWW 這種的輔助封裝,還有 GetAndGetBytes 和PostAndGetBytes。

ObservableWWW 的 API 都可以傳進去⼀個 ScheduledNotifier<T>() ,⽤來監聽下載進度的。Subscribe 之後傳回來的值則是,當前的進度。

 private void Start()
        {
            var progressObservable = new ScheduledNotifier<float>();

            ObservableWWW.GetAndGetBytes("http://liangxiegame.com/media/QFramework_v0.0.9.unitypackage", progress:progressObservable)
                         .Subscribe(bytes => 
                        { 
            
                        });

            progressObservable.Subscribe(progress =>
            {
                Debug.LogFormat("進度為:{0}", progress);
            });
        }

⽽且 ObservableWWW 的 Get 和 Post 請求都可以⾃⼰傳對應的 header 和 WWWForm。
除了常⽤的 Get 和 Post 請求,也對 AssetBundle 的載入也做了簡單的封裝。
提供了諸如 ObservableWWW.LoadFromCacheOrDownload 這樣的 API。如果想深⼊瞭解,可以參考 ObservableWWW.cs

另外多個一起下載:

  void Start()
        {
            var sikieduStream = ObservableWWW.Get("http://sikiedu.com");
            var qframeworkStream = ObservableWWW.Get("http://qframework.io");

            Observable.WhenAll(sikieduStream, qframeworkStream)
                      .Subscribe(responseTexts =>
                      {
                          Debug.Log(responseTexts[0].Substring(0, 100));
                          Debug.Log(responseTexts[1].Substring(0, 100));
                      });
        }

二.ReactiveCommand 

它提供了兩個 API,CanExecte和Execute

Execute ⽅法是被外部調⽤的。也就是這個 Command 的執⾏。這個很容易理解,只要外部調⽤的Execute 就會執⾏。⽽ CanExecute 則是內部使⽤的,並且對外部提供了只讀訪問。當 CanExecute 為 false 時,在外部調⽤ Execute 則該 Command 不會被執⾏。當 CanExecute 為 true 時,在外部調⽤ Execute 則該 Command 會被執⾏。其他的 Observable決定 CanExecute 為 false 或 true ,新建立的 ReactiveCommand 預設 CanExecute 為 true。

以下實現的是滑鼠左鍵按下輸出字元,擡起取消 :

 private void Start()
        {
            var mouseDownStream = Observable.EveryUpdate().Where(_ => Input.GetMouseButtonDown(0)).Select(_ => true);
            var mouseUpStream = Observable.EveryUpdate().Where(_ => Input.GetMouseButtonUp(0)).Select(_ => false);

            var isMouseUp = Observable.Merge(mouseUpStream, mouseDownStream);

            var reactiveCommand = new ReactiveCommand(isMouseUp, false);

            reactiveCommand.Subscribe(_ =>
            {
                Debug.Log("reactive command executed;");
            });

            Observable.EveryUpdate().Subscribe(_ =>
            {
                reactiveCommand.Execute();
            });
        }

當然 ReactiveCommand 也是可以被訂閱(Subscribe) 的,在訂閱之前呢,也可以使⽤ Where 等操作符進⾏事件操作。

三.ReactiveCollection 

類似於 List。

ObserverAdd // 當 新的 Item 新增則會觸發
ObserverRemove // 刪除
ObserverReplace // 替換(Update)
ObserverMove // 移動
ObserverCountChanged // 數量有改變(Add、Remove)

四.ReactiveDictionary 

功能與 Dictionary 一樣.

ObserverAdd // 當 新的 Item 新增則會觸發
ObserverRemove // 刪除
ObserverReplace // 替換(Update)
ObserverMove // 移動
ObserverCountChanged // 數量有改變(Add、Remove)

五.AsyncOperation載入場景

我們在非同步載入資源或者非同步載入場景的時候往往會⽤到 AsyncOperation。
UniRx 對 AsyncOperation 做了⽀持。使得載入操作可以很容易地監聽載入進度。

public class AsyncOperationExample : MonoBehaviour
{
   void Start()
   {
      var progressObservable = new ScheduledNotifier<float>();
      SceneManager.LoadSceneAsync(0).AsAsyncOperationObservable(progressObservable)
      .Subscribe(asyncOperation =>
      {
            Debug.Log("load done");
            Resources.LoadAsync<GameObject>("TestCanvas").AsAsyncOperationObservable()                                         
            .Subscribe(resourceRequest =>
            {
               Instantiate(resourceRequest.asset);
            });
      });
      progressObservable.Subscribe(progress =>
      {
            Debug.LogFormat("載入了:{0}", progress);
      });
   }
}