UniRx 基本使用

 

计时

 public class UniRxTimerExample : MonoBehaviour
    {
        private void Start()
        {
            Observable.Timer(TimeSpan.FromSeconds(5.0f))
                      .Subscribe(_ =>
                      {
                          Debug.Log("do something");
                      });
        }
    }

帧事件

 // 监听鼠标左键
Observable.EveryUpdate()
            .Subscribe(_ =>
             {
                          if (Input.GetMouseButtonDown(0))
                          {
                              Debug.Log("left mouse button clicked");
                              buttonClicked = true;
                          }
               });
Observable.EveryFixedUpdate().Subscribe(_ => {});
Observable.EveryEndOfFrame().Subscribe(_ => {});
Observable.EveryLateUpdate().Subscribe(_ => {});
Observable.EveryAfterUpdate().Subscribe(_ => {});
 

系统事件

// 除了 Update 还⽀持其他的事件,⽐如 ApplicationPause,Quit 等。
Observable.EveryApplicationPause().Subscribe(paused => {});
Observable.EveryApplicationFocus().Subscribe(focused => {});
Observable.EveryApplicationQuit().Subscribe(_ => {});

操作符

where 是⼀个过滤的操作,过滤掉不满⾜条件的事件。类似于if

Observable.EveryUpdate()
   .Where(_ => Input.GetMouseButtonUp(0))
   .Subscribe(_ =>
   {
     // do something
   }).AddTo(this);

First 获取第⼀个通过的事件.如果你只想条件只执行一次

Observable.EveryUpdate()
.Where(_ => Input.GetMouseButtonUp(0))
.First()
.Subscribe(_ => { /* do something */ })
.AddTo(this);
Observable.EveryUpdate()
.First(_ => Input.GetMouseButtonUp(0))
.Subscribe(_ => { /* do something */ })
.AddTo(this);

Take

// 双击判断  
//用了一个selectMany的技巧把传来的无效参数重新转换成一个事件源
            Observable.EveryUpdate().Where(_ => Input.GetMouseButtonDown(0))
                .SelectMany(_ =>Observable.EveryUpdate().Take(30).Where(___=>Input.GetMouseButtonDown(0)))
                .Subscribe(_=>print("double clicked"));

单击后拿取后面30个update元素再进行单击过滤

Select

 Observable.EveryUpdate().Where(_=>Input.GetMouseButtonDown(0)). Select((_, index) =>index)
.Subscribe(_ => print("点击了"+_+"次"));

SelectMany

 public class SelectMany : MonoBehaviour
    {
 
        void Start()
        {            
            var a = Observable.FromCoroutine(A);
            var b = Observable.FromCoroutine(B);
            var c = Observable.FromCoroutine(C);
 
            //对协程执行顺序进行任意组合  
            //原理是协程(可观察的)默认只会在结束后被观察到一次,A结束后被转成了B,B结束后又转成了C ,全部观察完后 输出end
            a.SelectMany(b.SelectMany(c)).Subscribe(_ => print("end"));
 
            //a.SelectMany(sa=> {
            //    print("a convered to b");
            //    return b;
            //}).Subscribe(_=>print("end"));
 
            //todo怎么组合带参数的协程?
        }
 
        IEnumerator A()
        {
            yield return new WaitForSeconds(1.0f);
            print("A");
        }
        IEnumerator B()
        {
            yield return new WaitForSeconds(1.0f);
            print("B");
        }
        IEnumerator C()
        {
            yield return new WaitForSeconds(1.0f);
            print("C");
        }
 
    }

 

AddTo 

添加到Unity 的 GameObject 或者 MonoBehaviour。GameObject 和 MonoBehaviour 可以获取到 OnDestroy 事件。也就是 GameObject 或者MonoBehaviour 的销毁事件.获取之后⽤来 进⾏与 UniRx 进⾏销毁事件的绑定,也就是当 GameObject 或者 MonoBehaviour 被销毁时,同样去销毁正在进⾏的 UniRx 任务。 当 GameObject 销毁时,就会调⽤ IDisposable 的 OnDispose 这个⽅法。

Observable.Timer(TimeSpan.FromSeconds(1.0f)
.Subscribe()
.AddTo(this);

 

SubscribeToInteractable / SubscribeToText

ugui 组件订阅,当发布者修改数据时,组件更新

 MySlider.OnValueChangedAsObservable()
                .SubscribeToText(MyText, x => Math.Round(x, 2).ToString());


 MyToggle.OnValueChangedAsObservable().SubscribeToInteractable(MyButton);

Trigger

.1. Trigger ⼤部分都是都是 XXXAsObsrevable 命名形式的。
2. 在使⽤ Trigger 的 GameObject 上都会挂上对应的 Observable XXXTrigger.cs 的脚本

除了 MonoBehaviour ,Trigger 也⽀持了其他组件类型,⽐如 RectTransform、Transform、UIBehaviour 等等。 

this.OnDestroyAsObservable()
.Subscribe(_ => {});

 

各种细分类型的 Update:
this.FixedUpdateAsObservable().Subscribe(_ => {});
this.LateUpdateAsObservable().Subscribe(_ => {});
this.UpdateAsObservable().Subscribe(_ => {});
 
还有各种碰撞的 Trigger:
this.OnCollisionEnterAsObservable().Subscribe(collision => {});
this.OnCollisionExitAsObservable().Subscribe(collision => {});
this.OnCollisionStayAsObservable().Subscribe(collision => {});
// 同样 2D 的也⽀持
this.OnCollision2DEnterAsObservable().Subscribe(collision2D => {});
this.OnCollision2DExitAsObservable().Subscribe(collision2D => {});
this.OnCollision2DStayAsObservable().Subscribe(collision2D => {});
 
⼀些脚本的参数监听:
this.OnEnableAsObservable().Subscribe(_ => {});
this.OnDisableAsObservable().Subscribe(_ => {});
 

UIBehaviour Triggle

[SerializeField] Button mButton;
[SerializeField] Toggle mToggle;
[SerializeField] Scrollbar mScrollbar;
[SerializeField] ScrollRect mScrollRect;
[SerializeField] Slider mSlider;
[SerializeField] InputField mInputField;
void Start()
{
   mButton.OnClickAsObservable().Subscribe(_ => Debug.Log("On Button Clicked"));
   mToggle.OnValueChangedAsObservable().Subscribe(on => Debug.Log("Toggle " + on));
   mScrollbar.OnValueChangedAsObservable().Subscribe(scrollValue => Debug.Log("Scrolled " + scrollValue));
   mScrollRect.OnValueChangedAsObservable().Subscribe(scrollValue => Debug.Log("Scrolled " + scrollValue);
   mSlider.OnValueChangedAsObservable().Subscribe(sliderValue => Debug.Log("Slider Value " + sliderValue));
   mInputField.OnValueChangedAsObservable().Subscribe(inputText => Debug.Log("Input Text: " + inputText));
   mInputField.OnEndEditAsObservable().Subscribe(result => Debug.Log("Result :" + result));
}

Subscribe 

Text resultText = GetComponent<Text>();
mInputField.OnValueChangedAsObservable().SubscribeToText(resultText);
mImage.OnBeginDragAsObservable().Subscribe(dragEvent => {});
mGraphic.OnDragAsObservable().Subscribe(dragEvent => {});
mText.OnEndDragAsObservable().Subscribe(dragEvent => {});
mImage.OnPointerClickAsObservable().Subscribe(clickEvent => {});

 

UnityEvent 

UnityEvent mEvent;
void Start()
{
   mEvent.AsObservable()
   .Subscribe(_ => 
   {
     // process event
   });
}

响应式属性ReactiveProperty

当任何时候,Age 的值被设置,就会通知所有 Subscribe 的回调函数。
⽽ Age 可以被 Subscribe 多次的。
并且同样⽀持 First、Where 等操作符。

public class ReactivePropertyExample : MonoBehaviour
    {
        public IntReactiveProperty Age = new IntReactiveProperty(0);
 
        void Start()
        {
            Age.Subscribe(age =>
            {
                Debug.Log("inner received age changed");
            });
 
            Age.Value = 10;
        }
    }
 
 
    public class PersonView
    {
        ReactivePropertyExample mReactiveProeprtyExample;
 
        void Init()
        {
            mReactiveProeprtyExample.Age.Subscribe((age) =>
            {
                Debug.Log(age);
            });
        }
    }
 public enum Mode
    {
        Add,
        Edit
    } 

public ReactiveProperty<Mode> Mode = new ReactiveProperty<Mode>(UniRxLesson.Mode.Add);

 mInputCtrl.Mode.Subscribe(mode =>
            {
                if (mode == Mode.Add)
                {
                    mEvenMaskObj.SetActive(false);
                }
                else
                {
                    mEvenMaskObj.SetActive(true);
                }
            });

 

MVC模式

 public class EnemyExample : MonoBehaviour
    {
        [SerializeField] EnemyModel mEnemy = new EnemyModel(200);
 
        void Start()
        {
            var attackBtn = transform.Find("Button").GetComponent<Button>();
            var HPText = transform.Find("Text").GetComponent<Text>();
 
            attackBtn.OnClickAsObservable()
                     .Subscribe(_ =>
                     {
                         mEnemy.HP.Value -= 99;
                     });
 
            mEnemy.HP.SubscribeToText(HPText);
 
            mEnemy.IsDead
                  .Where(isDead => isDead)
                  .Select(isDead => !isDead)
                  .SubscribeToInteractable(attackBtn);
        }
    }
 
    // Model
    public class EnemyModel
    {
        public ReactiveProperty<long> HP;
 
        public IReadOnlyReactiveProperty<bool> IsDead;
 
        public EnemyModel(long initialHP)
        {
            HP = new ReactiveProperty<long>(initialHP);
 
            IsDead = HP.Select(hp => hp <= 0).ToReactiveProperty();
        }
    }

Merge

UniRx 可以开启两个或多个事件流。并使⽤ Merge 进⾏事件流的合并,比如实现⿏标左键或右键点击时都会进⾏处理

var leftMouseClickStream = Observable.EveryUpdate().Where(_ => 
Input.GetMouseButtonDown(0));
var rightMouseClickStream = Observable.EveryUpdate().Where(_ => 
Input.GetMouseButtonDown(1));
 
Observable.Merge(leftMouseClickStream, rightMouseClickStream)
.Subscribe(_ => 
{
     // do something
});

Coroutine 

 public class Observable2YieldExample : MonoBehaviour
    {
        IEnumerator Delay1Second()
        {
            yield return Observable.Timer(TimeSpan.FromSeconds(1.0f)).ToYieldInstruction();
            Debug.Log("delay 1 seconds");
        }
 
        void Start()
        {
            StartCoroutine(Delay1Second());
        }
    }

WhenAll

 public class CoroutineSpawnExample : MonoBehaviour
    {
        IEnumerator A()
        {
            yield return new WaitForSeconds(1.0f);
            Debug.Log("A");
        }
 
        IEnumerator B()
        {
            yield return new WaitForSeconds(1.0f);
            Debug.Log("B");
        }
 
        void Start()
        {
            var aStream = Observable.FromCoroutine(_ => A());
            var bStream = Observable.FromCoroutine(_ => B());
 
            Observable.WhenAll(aStream, bStream)
                      .Subscribe(_ =>
                      {
                          Debug.Log("when all 处理了");
                      });
        }
    }
 public class AllButtonClickedOnceExample : MonoBehaviour
    {
        void Start()
        {
            var leftMouseClickedEvents = Observable.EveryUpdate().Where(_ => Input.GetMouseButtonDown(0)).First();
            var rightMouseClickedEvetns = Observable.EveryUpdate().Where(_ => Input.GetMouseButtonDown(1)).First();
 
            Observable.WhenAll(leftMouseClickedEvents, rightMouseClickedEvetns)
                      .Subscribe(_ =>
                      {
                          Debug.Log("mouse clicked");
                      });
        }
    }
}

 OnCompleted 

 public class OnCompletedExample : MonoBehaviour
    {
        void Start()
        {
            Observable.FromCoroutine(A)
                      .Subscribe(_ =>
                      {
                          Debug.Log("OnNext:");
                      }, () =>
                      {
                          Debug.Log("OnCompleted:");
                      });
        }
 
        IEnumerator A()
        {
            yield return new WaitForSeconds(2.0f);
        }
    }

Start 多线程

Observable.Start:开启⼀个线程流。

ObserveOnMainThread : 把 WhellAll 结果转到主线程上。这样 Subscribe ⾥的回调就可以使⽤Unity 的 API 了(Unity 的很多 API 不可以在其他线程中使⽤ )。

public class ThreadExample : MonoBehaviour
    {
        void Start()
        {
            var threadAStream = Observable.Start(() =>
            {
                Thread.Sleep(TimeSpan.FromSeconds(1));
                return 10;
            });
 
            var threadBStream = Observable.Start(() =>
            {
                Thread.Sleep(TimeSpan.FromSeconds(3));
                return 10;
            });
 
            Observable.WhenAll(threadAStream, threadBStream)
                      .ObserveOnMainThread()
                      .Subscribe(results =>
                      {
                          Debug.LogFormat("{0}:{1}", results[0], results[1]);
                      });
        }
    }

ObservableWWW

https://blog.csdn.net/dengshunhao/article/details/85391015

除了 Get 也⽀持了 Post,还有 GetWWW 和 PostWWW 这种的辅助封装,还有 GetAndGetBytes 和PostAndGetBytes。

ObservableWWW 的 API 都可以传进去⼀个 ScheduledNotifier<T>() ,⽤来监听下载进度的。Subscribe 之后传回来的值则是,当前的进度。

void Start()
        {
            ObservableWWW.Get("http://sikiedu.com")
                         .Subscribe(responseText =>
                         {
                             Debug.Log(responseText);
                         }, e =>
                         {
                             Debug.LogError(e);
                         });
        }
 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);
            });
        }
  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 

https://blog.csdn.net/dengshunhao/article/details/85391015

它提供了两个 API,CanExecte和Execute

Execute ⽅法是被外部调⽤的。也就是这个 Command 的执⾏。这个很容易理解,只要外部调⽤的Execute 就会执⾏。⽽ CanExecute 则是内部使⽤的,并且对外部提供了只读访问。当 CanExecute 为 false 时,在外部调⽤ Execute 则该 Command 不会被执⾏。当 CanExecute 为 true 时,在外部调⽤ Execute 则该 Command 会被执⾏。其他的 Observable决定 CanExecute 为 false 或 true ,新创建的 ReactiveCommand 默认 CanExecute 为 true。

当然 ReactiveCommand 也是可以被订阅(Subscribe) 的,在订阅之前呢,也可以使⽤ Where 等操作符进⾏事件操作。

 

 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();
            });
        }

 ReactiveCollection 

ObserverAdd // 当 新的 Item 添加则会触发
ObserverRemove // 删除
ObserverReplace // 替换(Update)
ObserverMove // 移动
ObserverCountChanged // 数量有改变(Add、Remove)

ReactiveDictionary 

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);
      });
   }
}

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值