我是靠谱客的博主 狂野小天鹅,最近开发中收集的这篇文章主要介绍UniRx入门纲要UniRx学习笔记,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

UniRx学习笔记

定时器

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

独立的Update

 public class UpdateExample : MonoBehaviour
{
enum ButtonState
{
None,
Clicked,
DoubleClicked
}
private void Start()
{
ButtonState buttonState = ButtonState.None;
bool buttonClicked = false;
//监听鼠标左键
Observable.EveryUpdate()
.Subscribe(_ =>
{
if (Input.GetMouseButtonDown(0))
{
print("left mouse button clicked");
buttonClicked = true;
}
});
//监听鼠标右键
Observable.EveryUpdate()
.Subscribe(_ =>
{
if (Input.GetMouseButtonDown(1))
{
print("right mouse button clicked");
buttonClicked = true;
}
});
Observable.EveryUpdate()
.Subscribe(_ =>
{
//监听状态
if (buttonClicked && buttonState == ButtonState.None)
{
buttonState = ButtonState.Clicked;
}
print(buttonState);
});
}
}

这种应用比较初级,随着学习的深入,会有更好的使用方法。

Observable.XXX().Subscribe() 是⾮常典型的 UniRx 格式。

只要理解什么意思就可以看懂⼤部分的 UniRx 的⽤法了。

⾸先解决词汇问题:

Observable: 可观察的,形容词,形容后边的词(Timer) 是可观察的,我们可以粗暴地把 Observable 后边的理解成发布者。

Timer: 定时器,名词,被 Observable 描述,所以是发布者,是事件的发送⽅。

Subscribe: 订阅,动词,订阅谁呢?当然是前边的 Timer,这⾥可以理解成订阅者,也就是事件的接

收⽅。

AddTo: 暂不⽤理解。

连起来则是:可被观察(监听)的.Timer().订阅()

顺下来应该是:订阅可被观察的定时器。

其概念关系很容易理解。

• Timer 是可观察的。

• 可观察的才能被订阅。

Observable.XXX().Subscribe();

可被观察(监听)的 XX,注册。

以上笔者从发布者和订阅者这个⻆度来进⾏的介绍,以便⼤家理解。

但是 UniRx 的侧重点,不是发布者和订阅者这两个概念如何使⽤,⽽是事件从发布者到订阅者之间的

过程如何处理。

所以两个点不重要,重要的是两点之间的线,也就是事件的传递过程。

 public class IntroExample : MonoBehaviour
{
private void Start()
{
Observable.EveryUpdate()//开启Update的事件监听
.Where(_ => Input.GetMouseButtonDown(0))//进行一个鼠标是否抬起的判断
.First()//只获取第一次的点击事件
.Subscribe(_=> {//订阅/处理事件
print("MouseButton Down.");
});
}
}

where操作符

  1. EveryUpdate 是事件的发布者。他会每帧会发送⼀个事件过来。

  2. Subscribe 是事件的接收者,接收的是 EveryUpdate 发送的事件。

  3. Where 则是在事件的发布者和接收者之间的⼀个过滤操作。会过滤掉不满⾜条件的事件。

    First操作符

    获取第一个通过的事件,First还可以传一个条件,所以上述代码可以不使用where,精简为:

    public class IntroExample : MonoBehaviour
    {
    private void Start()
    {
    Observable.EveryUpdate()//开启Update的事件监听
    .First(_ => Input.GetMouseButtonDown(0))//只获取第一次的点击事件
    .Subscribe(_=> {//订阅/处理事件
    print("MouseButton Down.");
    })
    .AddTo(this);
    }
    }
    

UGUI的支持

/****************************************************
文件:UIExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/9 17:8:53
功能:UniRx对UGUI的支持
*****************************************************/
using UnityEngine;
using System;
using System.Collections;
using UniRx;
using UniRx.Triggers;
using UnityEngine.UI;
namespace UniRxLesson
{
public class UIExample : MonoBehaviour
{
private void Start()
{
var button = transform.Find("Button").GetComponent<Button>();
button.OnClickAsObservable()
.Subscribe(_ =>
{
print("button clicked");
});
var toggle = transform.Find("Toggle").GetComponent<Toggle>();
toggle.OnValueChangedAsObservable()
.Subscribe(on =>
{
print(on);
});
var image = transform.Find("Image").GetComponent<Image>();
image.OnBeginDragAsObservable()
.Subscribe(_ =>
{
print("Begin Drag");
});
image.OnDragAsObservable()
.Subscribe(_ =>
{
print("On Dragging");
});
image.OnEndDragAsObservable()
.Subscribe(_ =>
{
print("End Drag");
});
}
}
}

使用UniRx可以非常方便的对UGUI进行事件发布和订阅,免去实现一些接口的工作。除此之外,UniRx还可以用在任何UNITY Event中。

响应式属性

/****************************************************
文件:ReactivePropertyExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/10 10:31:39
功能:UniRx的响应式属性示例
*****************************************************/
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using UniRx;
namespace UniRxLesson
{
public class ReactivePropertyExample : MonoBehaviour
{
public ReactiveProperty<int> Age = new ReactiveProperty<int>(0);
private void Start()
{
Age.Subscribe(age =>
{
print("inner recevied Age change"+age );
});
Age.Value = 10;//不管什么时候值发生改变,订阅改变事件的函数必定响应
}
}
public class PersonView
{
ReactivePropertyExample mReactivePropertyExample = null;
void Init()
{
mReactivePropertyExample.Age.Subscribe((age) =>
{
Debug.Log(age);
});
}
}
}

MVP(Model-View-Presenter)

/****************************************************
文件:EnemyExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/10 11:29:27
功能:MVP简单示例
*****************************************************/
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections;
using System.Collections.Generic;
using UniRx;
namespace UniRxLesson
{
public class EnemyExample : MonoBehaviour
{
EnemyModel enemy = new EnemyModel(200);
private void Start()
{
var btn_Attack = transform.Find("Button").GetComponent<Button>();
var txt_HPText = transform.Find("Text").GetComponent<Text>();
btn_Attack.OnClickAsObservable()
.Subscribe(_ =>
{
enemy.HP.Value -= 99;
});
enemy.HP.SubscribeToText(txt_HPText);
/* enemy.isDead
.Where(isDead => isDead)
.Subscribe(_ =>
{
btn_Attack.interactable = false;
});*/
enemy.isDead
//.Where(isDead => isDead)
.Select(isDead => !isDead)
.SubscribeToInteractable(btn_Attack);
//两种方法都行,其中Select()函数是个转换,转换的结果直接赋值到subscribeToInteractable中
}
}
public class EnemyModel
{
public LongReactiveProperty HP;
public IReadOnlyReactiveProperty<bool> isDead;
public EnemyModel(long initHP)
{
HP = new LongReactiveProperty(initHP);
isDead = HP.Select(hp => hp <= 0).ToReactiveProperty();
}
}
}

在 Unity 中,我们把 Scene 中的 GameObject 当做视图层,这些是在 Unity 的 Hierarchy 中定义的。

展示/控制层在 Unity 初始化时将视图层绑定。

SubscribeToText and SubscribeToInteractable 都是简洁的类似绑定的辅助函数。虽然这些⼯工具很简 单,但是⾮非常实⽤用。

在 Unity 中使⽤用开发体验⾮非常平滑,性能也很好,重要的是让你的代码更更简洁。

View -> ReactiveProperty -> Model -> RectiveProperty - View 完全⽤用响应式的⽅方式连接。UniRx 提供 了了所有的适配⽅方法和类,不不过其他的 MVVM (or MV*) 框架也可以使⽤用。UniRx/ReactiveProperty 只是 一个简单的⼯工具包。

Merge操作符

merge操作符用于合并多个事件流,相当于同时订阅两个事件流,只要任何一个事件流发生,订阅的函数和事件就会被执行。

/****************************************************
文件:MergeExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/10 14:34:18
功能:Merge操作符的使用
*****************************************************/
using UnityEngine;
using UniRx;
using System;
using System.Collections;
using System.Collections.Generic;
namespace UniRxLesson
{
public class MergeExample : MonoBehaviour
{
private void Start()
{
var leftClickedEvents = Observable.EveryUpdate().Where(_ => Input.GetMouseButtonDown(0));
var rightClickedEvents = Observable.EveryUpdate().Where(_ => Input.GetMouseButtonDown(1));
Observable.Merge(leftClickedEvents, rightClickedEvents)
.Subscribe(_ =>
{
print("mouse Clicked");
});
}
}
}

用Merge和First做一个UI按钮事件锁

/****************************************************
文件:PanelEventLockExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/10 14:48:52
功能:实现一个UI界面按钮锁的功能
*****************************************************/
using UnityEngine;
using System;
using UniRx;
using UnityEngine.UI;
namespace UniRxLesson
{
public class PanelEventLockExample : MonoBehaviour
{
private void Start()
{
var btn_A = transform.Find("ButtonA").GetComponent<Button>();
var btn_B = transform.Find("ButtonB").GetComponent<Button>();
var btn_C = transform.Find("ButtonC").GetComponent<Button>();
var aEvents = btn_A.OnClickAsObservable();
var bEvents = btn_B.OnClickAsObservable();
var cEvents = btn_C.OnClickAsObservable();
Observable.Merge(aEvents, bEvents, cEvents)
.First()
.Subscribe(_ =>
{
print("Button clicked");
Observable.Timer(TimeSpan.FromSeconds(1.0f))
.Subscribe(__ =>
{
gameObject.SetActive(false);
});
});
}
}
}

Select的选择操作(操作后返回一个泛型)

 private void Start()
{
var btn_A = transform.Find("ButtonA").GetComponent<Button>();
var btn_B = transform.Find("ButtonB").GetComponent<Button>();
var btn_C = transform.Find("ButtonC").GetComponent<Button>();
var aEvents = btn_A.OnClickAsObservable().Select(_ => "A");
var bEvents = btn_B.OnClickAsObservable().Select(_ => "B");
var cEvents = btn_C.OnClickAsObservable().Select(_ => "C");
Observable.Merge(aEvents, bEvents, cEvents)
.First()
.Subscribe(btnID =>//用btnID接收事件经过Select操作后的返回值
{
print("Button clicked"+btnID);
Observable.Timer(TimeSpan.FromSeconds(1.0f))
.Subscribe(__ =>
{
gameObject.SetActive(false);
});
});
}

第二章Unity和UniRx

UGUI的增强

/****************************************************
文件:UGUIExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/10 15:39:12
功能:UniRx对unity UGUI的增强
*****************************************************/
using UnityEngine;
using UniRx;
using UnityEngine.UI;
namespace UniRxLesson
{
public class UGUIExample : MonoBehaviour
{
[SerializeField] Button mButton;
[SerializeField] Toggle mToggle;
[SerializeField] Scrollbar mScrollbar;
//[SerializeField] ScrollRect mScrollRect;
[SerializeField] Slider mSlider;
[SerializeField] InputField mInputField;
[SerializeField] Text mText;
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));
//mInputField.OnEndEditAsObservable().SubscribeToText(mText);
mInputField.OnValueChangedAsObservable().SubscribeToText(mText);//一个绑定操作,非常方便
}
}
}

Unity ⽣命周期 与 Trigger

对于 Unity 的 Observable 增强,我们在第⼀章就接触过了。

Observable.EveryUpdate() 就是⽀持的 Unity 的 API。

单单 Update 就是⽀持⾮常多细分类型的 Update 事件捕获。

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(_ => {}):

学习了以上这些,就不⽤再去创建⼀个单例类去实现⼀个诸如“应⽤程序退出事件监听”这种逻辑了。

命名⼏⾏代码就可以搞定的事情,何必再去创建⼀个类去搞定?

Trigger 简介

Observable.EveryUpdate() 这个 API 有的时候在某个脚本中实现,需要绑定 MonoBehaviour 的⽣命周 期(主要是 OnDestroy),当然也有的时候是全局的,⽽且永远不会被销毁的。

需要绑定 MonoBehaviour ⽣命周期的 EveryUpdate。只需要⼀个 AddTo 就可以进⾏绑定了。⾮常简

单,代码如下。

Observable.EveryUpdate()
.Subscribe(_ => {})
.AddTo(this);

但其实有更简洁的实现:

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

这种类型的 Observable 是什么呢?

答案是:Trigger,即触发器。

字如其意,很容易理解。

Trigger 类型的关键字

触发器,字如其意,是当某个事件发⽣时,则会将该事件发送到 Subscribe 函数中,⽽这个触发器,

本身是⼀个功能脚本,这个脚本挂在 GameObject 上,来监听 GameObject 的某个事件发⽣,事件发

⽣则会回调给注册它的 Subscribe 中。

触发器的操作和其他的事件源 (Observable) 是⼀样的,都⽀持 Where、First、Merge 等操作符。

Trigger 类型的 Observable 和我们之前讲的所有的 Observable 在表现上有⼀点不⼀样:

1. Trigger ⼤部分都是都是 XXXAsObsrevable 命名形式的。

2. 在使⽤ Trigger 的 GameObject 上都会挂上对应的 Observable XXXTrigger.cs 的脚本。

Trigger 在此之前我们是接触过的。

AddTo() 这个 API 其实是封装了⼀种 Trigger: ObservableDestroyTrigger。

2顾名思义,就是当 GameObject 销毁时获取事件的⼀个触发器。

⼀般的 Trigger 都会配合 MonoBehaviour ⼀起使⽤。

⽐如 ObservableDestroyTrigger 的使⽤代码如下:

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

除了 Destroy 还有⾮常多的 Trigger。

⽐如各种细分类型的 Update:

this.FixedUpdateAsObservable().Subscribe(_ => {});
this.LateUpdateAsObservable().Subscribe(_ => {});
this.UpdateAsObservable().Subscribe(_ => {});

还有各种碰撞的 Trigger:

this.OnCollisionEnterAsObservable(collision => {});
this.OnCollisionExitAsObservable(collision => {});
this.OnCollisionStayAsObservable(collision => {});
// 同样 2D 的也⽀持
this.OnCollision2DEnterAsObservable(collision2D => {});
this.OnCollision2DExitAsObservable(collision2D => {});
this.OnCollision2DStayAsObservable(collision2D => {});

⼀些脚本的参数监听:

this.OnEnableAsObservable().Subscribe(_ => {});
this.OnDisableAsObservable().Subscribe(_ => {});

3.除了 MonoBehaviour ,Trigger 也⽀持了其他组件类型,⽐如 RectTransform、Transform、

UIBehaviour 等等。这⾥不再赘述。

详情可以查看 ObservableTriggerExtensions.cs 和 ObervableTriggerExtensions.Component.cs 中的 API。

UI Trigger

在项⽬中⽤的⽐较多的⼏个 Trigger:

mImage.OnBeginDragAsObservable().Subscribe(dragEvent => {});
mGraphic.OnDragAsObservable().Subscribe(dragEvent => {});
mText.OnEndDragAsObservable().Subscribe(dragEvent => {});
mImage.OnPointerClickAsObservable().Subscribe(clickEvent => {});

UniRx对协程的支持

UniRx 对 Unity 的 Coroutine 也提供⽀持,可以将⼀个 Coroutine 转化为事件源(Observable)

/****************************************************
文件:RxCoroutineTest.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/10 17:36:21
功能:UniRx对协程的支持
*****************************************************/
using UnityEngine;
using UniRx;
using UniRx.Triggers;
using System.Collections;
namespace UniRxLesson
{
public class RxCoroutineTest : MonoBehaviour
{
IEnumerator CoroutineA()
{
yield return new WaitForSeconds(1.0f);
Debug.Log("A");
}
void Start()
{
Observable.FromCoroutine(_ => CoroutineA())
.Subscribe(_ =>
{
// do something
print("666");
}).AddTo(this);
}
}
}

当然也⽀持将 Observable 转化为⼀个 Coroutine 中的 yield 对象

⽐如:

/****************************************************
文件:Rx2YieldTest.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/10 17:40:15
功能: Observable 转化为⼀个 Coroutine 中的 yield 对象
*****************************************************/
using UnityEngine;
using UniRx;
using System;
using System.Collections;
using UniRx.Triggers;
namespace UniRxLesson
{
public class Rx2YieldTest : MonoBehaviour
{
IEnumerator Delay1Second()
{
yield return
Observable.Timer(TimeSpan.FromSeconds(1.0f)).ToYieldInstruction();
Debug.Log("B");
}
void Start()
{
StartCoroutine(Delay1Second());
}
}
}

WhenAll操作符

WhenAll在协程上的用法
/****************************************************
文件:WhenAllCoroutineExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/11 9:39:56
功能:UniRx when all操作符
*****************************************************/
using UnityEngine;
using UniRx;
using System.Collections;
namespace UniRxLesson
{
public class WhenAllCoroutineExample : MonoBehaviour
{
IEnumerator A()
{
yield return new WaitForSeconds(1.0f);
Debug.Log("A");
}
IEnumerator B()
{
yield return new WaitForSeconds(2.0f);
Debug.Log("B");
}
void Start()
{
var aStream = Observable.FromCoroutine(_ => A());
var bStream = Observable.FromCoroutine(_ => B());
Observable.WhenAll(aStream, bStream)
.Subscribe(_ =>
{
print("C");
}).AddTo(this);
}
}
}
WhenAll在按钮点击上的用法
/****************************************************
文件:ButtonAllClickedOnce.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/11 9:44:40
功能:所有按钮一次点击后事件
*****************************************************/
using UnityEngine;
using UniRx;
using System.Collections;
using UnityEngine.UI;
namespace UniRxLesson
{
public class ButtonAllClickedOnce : MonoBehaviour
{
[SerializeField] Button mButtonA;
[SerializeField] Button mButtonB;
[SerializeField] Button mButtonC;
void Start()
{
var aStream = mButtonA.OnClickAsObservable().First();
var bStream = mButtonB.OnClickAsObservable().First();
var cStream = mButtonC.OnClickAsObservable().First();
Observable.WhenAll(
aStream,
bStream,
cStream)
.Subscribe(_ =>
{
Debug.Log("clicked");
}).AddTo(this);
}
}
}

事件流的结束 OnCompleted

/****************************************************
文件:onCompletedExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/11 10:40:13
功能:事件流的结束
*****************************************************/
using UnityEngine;
using UniRx;
using System.Collections;
using System;
namespace UniRxLesson
{
public class onCompletedExample : MonoBehaviour
{
private void Start()
{
/*Observable.Timer(TimeSpan.FromSeconds(1.0f)).Subscribe(_=> print("OnNext after 1 Sec "),
()=> print("onComplete")
);*/
//Observable.EveryUpdate().First().Subscribe(_ =>
//{
//
Debug.Log("OnNext:First");
//}, () =>
//{
//
Debug.Log("OnCompleted");
//}).AddTo(this);
Observable.FromCoroutine(A)
.Subscribe(_ =>
{
Debug.Log("OnNext:");
}, () =>
{
Debug.Log("OnCompleted:");
});
}
IEnumerator A()
{
yield return new WaitForSeconds(2.0f);
}
}
}

协程有Oncompleted事件,EveryUpdate没有,只有OnNext事件,默认Subscribe后面触发的是OnNext事件。正因为有OnCompleted事件,才有WhenAll操作。

Start:让多线程更简单

多线程,是作为⾼级开发者必须具备的⼀种技术。了解了多线程可以让我们充分利⽤多核移动端的计

算优势,也可以让我们的游戏体验更平滑。

在 Unity 中我们⼀般⽤ Thread.Start 开启⼀个线程。当逻辑⾮常复杂的时候多线程⾮常难以管理。

⽽ UniRx 改善了这⼀种状况。

⼀个”当所有线程运⾏完成后,在主线程执⾏某个任务” 这个功能,使⽤ UniRx 实现如下:

/****************************************************
文件:ThreadExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/11 11:22:17
功能:UniRx管理多线程
*****************************************************/
using UnityEngine;
using UniRx;
using System.Collections;
using System;
using System.Threading;
namespace UniRxLesson
{
public class ThreadExample : MonoBehaviour
{
private void Start()
{
var threadAStream = Observable.Start(() =>
{
Thread.Sleep(TimeSpan.FromSeconds(1.0f));
return 10;
});
var threadBStream = Observable.Start(() =>
{
Thread.Sleep(TimeSpan.FromSeconds(3.0f));
return 10;
});
Observable.WhenAll(threadAStream, threadBStream)
.ObserveOnMainThread()
.Subscribe(results => print(results[0] + ":" + results[1]));
}
}
}

3 秒后,输出的结果如下:

10:10

这⾥有两个新的 API,⼀个是 Observable.Start,这个 API 意思开启⼀个线程流。

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

使⽤ UniRx 来处理线程逻辑⾮常简单。

线程和 Coroutine (协程)都可以使⽤ WhenAll 这种操作符。

ObservableWWW 优雅的⽹络请求操作

以往我们不管使⽤ WWW 还是 UnityWebRequest 都要使⽤ Coroutine 去驱动。

但是使⽤协程写出来的代码,需要⼀堆判断,导致代码⾮常混乱。

⽽ UniRx 则是以以往⼀样简练的⻛格提供了对⽹络请求的⽀持。

代码如下:

/****************************************************
文件:WWWExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/11 11:49:55
功能:UniRx优雅的网络请求操作
*****************************************************/
using UnityEngine;
using UniRx;
using System.Collections;
using System;
namespace UniRxLesson
{
public class WWWExample : MonoBehaviour
{
private void Start()
{
ObservableWWW.Get("baidu.com")
.Subscribe(responseText =>
{
print(responseText.Substring(0, 10));
},
e=>
{
Debug.LogError(e);
});
}
}
}
支持whenAll操作:
/****************************************************
文件:WWWWhenAllExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/11 11:55:21
功能:WWW 中的WhenALL操作
*****************************************************/
using UnityEngine;
using UniRx;
using System.Collections;
using System;
namespace UniRxLesson
{
public class WWWWhenAllExample : MonoBehaviour
{
private void Start()
{
var aStream = ObservableWWW.Get("baidu.com");
var bStream = ObservableWWW.Get("sikiedu.com");
Observable.WhenAll(aStream, bStream)
.Subscribe(responseText =>
{
print(responseText[0].Substring(0, 10));
print(responseText[1].Substring(0, 100));
});
}
}
}
下载文件
/****************************************************
文件:ProgressExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/11 12:24:0
功能:用UniRx下载文件,并且显示进度
*****************************************************/
using UnityEngine;
using UniRx;
using System.Collections;
using System;
namespace UniRxLesson
{
public class ProgressExample : MonoBehaviour
{
private void Start()
{
var progressObserable = new ScheduledNotifier<float>();
ObservableWWW.GetAndGetBytes("http://liangxiegame.com/media/QFramework_v0.0.9.unitypackage", progress: progressObserable)
.Subscribe(bytes =>
{
},
e=>
{
Debug.Log(e);
});
progressObserable.Subscribe(progress =>
{
Debug.LogFormat("进度为:{0}", progress);
});
}
}
}

ReactiveCommand

我们先来看下 ReactiveCommand 定义 :

public interface IReactiveCommand<T> : IObservable<T>
{
IReadOnlyReactiveProperty<bool> CanExecute { get; }
bool Execute(T parameter);
}

它提供了两个 API:

• CanExecte

• Execute

Execute ⽅法是被外部调⽤的。也就是这个 Command 的执⾏。这个很容易理解,只要外部调⽤的

Execute 就会执⾏。

⽽ CanExecute 则是内部使⽤的,并且对外部提供了只读访问。

当 CanExecute 为 false 时,在外部调⽤ Execute 则该 Command 不会被执⾏。

当 CanExecute 为 true 时,在外部调⽤ Execute 则该 Command 会被执⾏。

是什么决定 CanExecute 为 false 或 true 呢?

答案是其他的 Observable。

新创建的 ReactiveCommand 默认 CanExecute 为 true。

/****************************************************
文件:ReactiveCommandExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/11 14:45:40
功能:ReactiveCommand示例
*****************************************************/
using UnityEngine;
using UniRx;
using System.Collections;
using System;
namespace UniRxLesson
{
public class ReactiveCommandExample : MonoBehaviour
{
private void Start()
{
var reactiveCommand = new ReactiveCommand();
reactiveCommand.Subscribe(_ =>
{
print("执行");
});
reactiveCommand.Execute();
reactiveCommand.Execute();
reactiveCommand.Execute();
}
}
}

输出的结果是:

执行

执行

执行

⾮常地简单,只要调⽤ Execute。command 就会通知 Subscribe 的回调(因为 CanExecute 为 true)。

CanExecute 的开启关闭是由 Observable (事件源)决定的。

/****************************************************
文件:MouseDownUPExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/11 14:49:9
功能:熟悉ReactiveCommand中的CanExcuse属性
*****************************************************/
using UnityEngine;
using UniRx;
using UniRx.Triggers;
using System.Collections;
using System;
namespace UniRxLesson
{
public class MouseDownUPExample : MonoBehaviour
{
private void Start()
{
var leftMouseDownStream = this.UpdateAsObservable().
Where(_ => Input.GetMouseButtonDown(0))
.Select(_ => true);
var leftMouseUPStream = this.UpdateAsObservable().
Where(_ => Input.GetMouseButtonUp(0))
.Select(_ => false);
var isMouseDown = Observable.Merge(leftMouseDownStream, leftMouseUPStream);
var reactiveCommand = new ReactiveCommand(isMouseDown, false);
reactiveCommand.Subscribe(x =>
{
print("reactiveCommand"+x.ToString());
});
this.UpdateAsObservable().Subscribe(_ => reactiveCommand.Execute());
}
}
}

在上面的示例代码中,鼠标按下事件通过Select操作符让其Observable返回一个true,鼠标抬起事件通过Select操作符让其Observable事件源返回一个false。用Merge操作符将两个事件源合并成一个事件源作为ReactiveCommand的监听事件源,所以reactiveCommand中的CanExcuse属性则有合并后的事件源isMouseDown的返回值决定。当鼠标按下时,返回true,每帧调用的Excuse函数会被执行,输出字符串,抬起时,每帧调用的Excuse函数不会被执行,就不会在控制台输出字符串。

ReactiveCollection 与 ReactiveDictionary

ReactiveCollection

ReactiveCollection 类似于 List。

我们可以使⽤如下的操作符:

ObserverAdd // 当 新的 Item 添加则会触发

ObserverRemove // 删除

ObserverReplace // 替换(Update)

ObserverMove // 移动

ObserverCountChanged // 数量有改变(Add、Remove)

ReactiveCollection 示例代码:

/****************************************************
文件:ReactiveCollectionExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/11 15:36:55
功能: ReactiveCollection示例
*****************************************************/
using UnityEngine;
using UniRx;
namespace UniRxLesson
{
public class ReactiveCollectionExample : MonoBehaviour
{
ReactiveCollection<int> mAges = new ReactiveCollection<int> { 1,2,3,4,5};
void Start()
{
mAges.ObserveAdd()
.Subscribe(addAge =>
{
Debug.LogFormat("add:{0}",addAge);
});
mAges.ObserveRemove()
.Subscribe(removedAge =>
{
Debug.LogFormat("remove:{0}",removedAge);
});
mAges.ObserveCountChanged()
.Subscribe(count =>
{
Debug.LogFormat("count:{0}",count);
});
foreach (var age in mAges)
{
Debug.Log(age);
}
mAges.Add(6);
mAges.Remove(2);
}
}
}

输出结果为

1

2

3

4

5

add:Index:5 Value:6

count:6

remove:Index:1 Value:2

count:5

ReactiveDictionary

ReactiveDictionary 功能与 Dictionary ⼀样。

同样地,它⽀持了⼏个操作符:

ObserverAdd // 当 新的 Item 添加则会触发

ObserverRemove // 删除

ObserverReplace // 替换(Update)

ObserverMove // 移动

ObserverCountChanged // 数量有改变(Add、Remove)

示例代码如下:

/****************************************************
文件:ReactiveDictionaryExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/11 15:40:0
功能:ReactiveDictionary示例
*****************************************************/
using UniRx;
using UnityEngine;
namespace UniRxLesson
{
public class ReactiveDictionaryExample : MonoBehaviour
{
private ReactiveDictionary<string, string> mLanguageCode = new
ReactiveDictionary<string, string>(){ {"en","英语"},{"cn","中⽂"}};
// Use this for initialization
void Start()
{
mLanguageCode.ObserveAdd()
.Subscribe(addedLanguage =>
{
Debug.LogFormat("add:{0}", addedLanguage.Value);
});
mLanguageCode.ObserveRemove()
.Subscribe(removedLanguage =>
{ Debug.LogFormat("remove:{0}", removedLanguage.Value); });
mLanguageCode.ObserveCountChanged()
.Subscribe(count =>
{
Debug.LogFormat("count:{0}", count);
});
mLanguageCode.Add("jp", "⽇语");
mLanguageCode.Remove("en");
}
}
}

输出结果为

add:⽇语

count:3

remove:英语

count:2

加载场景 AsyncOperation

我们在异步加载资源或者异步加载场景的时候往往会⽤到 AsyncOperation。

UniRx 对 AsyncOperation 做了⽀持。使得加载操作可以很容易地监听加载进度。

示例代码如下:

/****************************************************
文件:AsyncOperationExample.cs
作者:Paul
邮箱: 794451358@qq.com
日期:2019/10/11 15:48:35
功能:用UniRx进行异步操作
*****************************************************/
using UnityEngine;
using UniRx;
using UnityEngine.SceneManagement;
namespace UniRxLesson
{
public class AsyncOperationExample : MonoBehaviour
{
private void Start()
{
var progressObserable = new ScheduledNotifier<float>();
SceneManager.LoadSceneAsync(0).AsAsyncOperationObservable(progress: progressObserable).Subscribe(asyncOperation =>
{
print("load Done");
asyncOperation.allowSceneActivation = true;
Resources.LoadAsync<GameObject>("TestCanvas").AsAsyncOperationObservable(progressObserable).Subscribe(resourceRequest =>
{
GameObject.Instantiate(resourceRequest.asset);
});
progressObserable.Subscribe(progress =>
{
Debug.LogFormat("已经加载了{0}", progress);
});
});
}
}
}

最后

以上就是狂野小天鹅为你收集整理的UniRx入门纲要UniRx学习笔记的全部内容,希望文章能够帮你解决UniRx入门纲要UniRx学习笔记所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部