Unity UniRX中文教程-Chinar

37 篇文章 5 订阅

Chinar blog www.chinar.xin


UnitRx 响应式编程



本文提供全流程,中文翻译。

Chinar 坚持将简单的生活方式,带给世人!

(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例)

Chinar —— 心分享、心创新!

助力学习理解 UniRx 响应式编程的函数、写法

为新手节省宝贵的时间,避免采坑!

Chinar 教程效果:暂时留空



全文高清图片,点击即可放大观看 (很多人竟然不知道)


1

Intro —— 简介


UniRx ——是 Unity 商店中一个免费插件,它为我们提供了一种 响应式编程 的方式

帮助我们解决 代码耦合、异步逻辑难以控制 等问题

由于其简化了逻辑与代码量,学会后代码的可读性也不错,Chinar 极力推荐,此等神器级别插件


UniRx (或 Unity 项目-商店直接下载导入)


2

EveryUpdate —— 更新


观察.Update.订阅(要做的事)

UniRx 就是这样的写法,其他写法主体几乎不变,只是扩展
New举例子黑白88

点击鼠标左右键,分别输出 “鼠标左键”、“鼠标右键”

// ========================================================
// 描述:UniRX - Update
// 作者:Chinar 
// 创建时间:2018-11-14 16:27:35
// 版 本:1.0
// ========================================================
using UniRx;
using UnityEngine;

public class ChinarUpdate : MonoBehaviour
{
    /// <summary>
    /// 初始化函数
    /// </summary>
    void Start()
    {
        //观察.Update.订阅(要做的事)
        Observable.EveryUpdate().Subscribe(_ =>
        {
            if (Input.GetMouseButtonDown(0))
            {
                print("鼠标左键");
            }
        });
        Observable.EveryUpdate().Subscribe(_ =>
        {
            if (Input.GetMouseButtonDown(1))
            {
                print("鼠标右键");
            }
        });
    }
}

注意:后边就不全粘所有代码了,只具体到完整函数,无特殊标记,代码都在Start()函数中写


3

First —— 首次执行

AddTo —— 控制生命周期


First(条件) —— 条件:只在第一次满足条件时,通过

AddTo(对象)——事件流的生命周期

New举例子黑白88

首次点击鼠标左键,输出“只执行一次”,以后不再执行

    void Start()
    {
        Observable.EveryUpdate()                   //观察
            .First(_ => Input.GetMouseButtonUp(0)) //条件
            .Subscribe(_ => print("只执行一次"))        //订阅
            .AddTo(this);                          //给事件流添加声明周期(PS:何时消失)
    }
    void Start()
    {
        //如果不添加 this ,那 Observable就是全局的,这个方法在重载场景时不会被释放,会无限叠加
        Observable.EveryUpdate().Subscribe(_ => print("Chinar")).AddTo(this);
        this.UpdateAsObservable().Subscribe(_ => print("Chinar")); //等同于上边:省去了AddTo,this指明了事件流的对象生命
    }

4

Ui Event —— 界面事件交互


< 1. win+R 打开运行 输入cmd 控制台中输入
ping qiniu.chinar.xin 就是 —— ping空格你自定义的域名

2. 或者 左侧栏融合CDN域名管理 中查看域名状态(添加CNAME后,刷新可能会有延迟)>

using UniRx;
using UniRx.Triggers;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;


/// <summary>
/// UI相关、按钮、图片、文本框
/// 脚本挂载:Canvas
/// </summary>
public class ChinarUguiOnClick : MonoBehaviour
{
    private ReactiveProperty<int> testIntProperty = new ReactiveProperty<int>(88); //指明响应属性 int,值88


    /// <summary>
    /// 初始化函数
    /// </summary>
    void Start()
    {
        //按钮的事件绑定
        //不添加 add to,绑定的监听函数不会叠加
        transform.Find("Button").GetComponent<Button>().OnClickAsObservable().Subscribe(_ => print("按钮事件被执行"));
        transform.Find("Reload Button").GetComponent<Button>().OnClickAsObservable().Subscribe(_ => { SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex); }); //重载当前场景

        //图片的事件注册
        var image = transform.Find("Image").GetComponent<Image>();
        image.OnBeginDragAsObservable().Subscribe(_ => print("开始拖动"));
        image.OnDragAsObservable().Subscribe(_ =>
        {
            print("正在拖动");
            image.transform.position = Input.mousePosition; //移动图
        });
        image.OnEndDragAsObservable().Subscribe(_ => print("拖动完成"));

        //响应 int 直接订阅 Text
        testIntProperty.SubscribeToText(GameObject.Find("Text Subscribe").GetComponent<Text>());
    }
}

New举例子黑白88
在这里插入图片描述


4.1

Button —— AsObservable


GetComponent<Button>().OnClickAsObservable().Select(_=>"A")//按钮绑定

GetComponent<Button>().OnPointerClickAsObservable().Subscribe();//支持Ui Event各种事件

4.2

Button —— AsObservable


GetComponent<Button>().OnClickAsObservable().Select(_=>"A")//按钮绑定

GetComponent<Button>().OnPointerClickAsObservable().Subscribe();//支持Ui Event各种事件

5

Coroutine —— 协程


Observable.FromCoroutine(协程函数) —— 协程转 Observable

Observable.Timer(TimeSpan.FromSeconds(1)).ToYieldInstruction() —— Observable 转 Yield
New举例子黑白88

    void Start()
    {
        Observable.FromCoroutine(TestIEnumerator); //协程转 Observable
    }


    private IEnumerator TestIEnumerator()
    {
        yield return Observable.Timer(TimeSpan.FromSeconds(1)).ToYieldInstruction(); // 转 指令、
        print("Chinar Test-Func");
    }

6

WhenAll —— 等待执行完毕


Where() —— 当多个事件流,需要根据逻辑满足所有都执行后,才触发执行
New举例子黑白88

1:等待2个协程执行完毕
2:当所有事件执行完毕后

    void Start()
    {
        //第一种:等待协程都执行完毕
        var streamA = Observable.FromCoroutine(A);
        var streamB = Observable.FromCoroutine(B);
        Observable.WhenAll(streamA, streamB).Subscribe(_ => print("WenAll执行成功!"));

        //第二种:所有操作执行一次后,执行以下订阅
        var event1 = this.UpdateAsObservable().Where(_ => Input.GetMouseButtonDown(0)).First();
        var event2 = this.UpdateAsObservable().Where(_ => Input.GetMouseButtonDown(1)).First();
        Observable.WhenAll(event1, event2).Subscribe(_ => print("左右键执行一次后,执行操作!"));
    }


    IEnumerator A()
    {
        yield return new WaitForSeconds(1);
        print("A");
    }


    IEnumerator B()
    {
        yield return new WaitForSeconds(2);
        print("B");
    }

7

Thread —— 线程


Observable.Start() —— 开启一个线程

ObserveOnMainThread() —— 线程结果返回到主线程中,在主线程中观察
New举例子黑白88

    void Start()
    {
        var stream1 = Observable.Start(() =>
        {
            Thread.Sleep(5000);//5000毫秒
            print("等待了5秒");
            return 1;
        }); //线程1
        var stream2 = Observable.Start(() =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            print("等待2秒");
            return 2;
        }); //线程2

        
        Observable.WhenAll(stream1, stream2).ObserveOnMainThread().Subscribe(_ => //当线程执行完毕,将其他线程中的值,返回到主线程中
        {
            print(_[0]);
            print(_[1]);
        });
    }

执行顺序
在这里插入图片描述


8

ObservableWWW —— RX-WWW请求


new ScheduledNotifier<float>() —— 声明一个预定进度对象

ObserveOnMainThread() —— 线程结果返回到主线程中,在主线程中观察
New举例子黑白88

        //第一个 print,请求正常信息
        //第二个 print,错误信息
        ObservableWWW.Get("http://www.chinar.xin/asdf").Subscribe(print, print);//请求一个错误的网路地址
    void Start()
    {
        var slider           = GameObject.Find("Slider").GetComponent<Slider>();                                                                    //滑动器
        var progressText     = GameObject.Find("ProgressText").GetComponent<Text>();                                                                //进度条文本
        var progressNotifier = new ScheduledNotifier<float>();                                                                                      //RX 预定通知 float
        ObservableWWW.GetAndGetBytes("http://www.chinar.xin/TestUpdate/granulesprite.unity3d", progress: progressNotifier).Subscribe(bytes => { }); //下载完成,做储存
        progressNotifier.Subscribe(progressFloat => { slider.value = progressFloat; });                                                             //更新进度
        progressNotifier.SubscribeToText(progressText);                                                                                             //进度值显示在 progressText
    }

在这里插入图片描述


7

Thread —— 线程


Observable.Start() —— 开启一个线程

ObserveOnMainThread() —— 线程结果返回到主线程中,在主线程中观察
New举例子黑白88

    void Start()
    {
        var stream1 = Observable.Start(() =>
        {
            Thread.Sleep(4000);//4000毫秒
            print("等待了4秒");
            return 1;
        }); //线程1
        var stream2 = Observable.Start(() =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            print("等待2秒");
            return 2;
        }); //线程2

        
        Observable.WhenAll(stream1, stream2).ObserveOnMainThread().Subscribe(_ => //当线程执行完毕,将其他线程中的值,返回到主线程中
        {
            print(_[0]);
            print(_[1]);
        });
    }

执行顺序
在这里插入图片描述


7

Thread —— 线程


Observable.Start() —— 开启一个线程

ObserveOnMainThread() —— 线程结果返回到主线程中,在主线程中观察
New举例子黑白88

    void Start()
    {
        var stream1 = Observable.Start(() =>
        {
            Thread.Sleep(4000);//4000毫秒
            print("等待了4秒");
            return 1;
        }); //线程1
        var stream2 = Observable.Start(() =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            print("等待2秒");
            return 2;
        }); //线程2

        
        Observable.WhenAll(stream1, stream2).ObserveOnMainThread().Subscribe(_ => //当线程执行完毕,将其他线程中的值,返回到主线程中
        {
            print(_[0]);
            print(_[1]);
        });
    }

执行顺序
在这里插入图片描述


7

Thread —— 线程


Observable.Start() —— 开启一个线程

ObserveOnMainThread() —— 线程结果返回到主线程中,在主线程中观察
New举例子黑白88

    void Start()
    {
        var stream1 = Observable.Start(() =>
        {
            Thread.Sleep(4000);//4000毫秒
            print("等待了4秒");
            return 1;
        }); //线程1
        var stream2 = Observable.Start(() =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            print("等待2秒");
            return 2;
        }); //线程2

        
        Observable.WhenAll(stream1, stream2).ObserveOnMainThread().Subscribe(_ => //当线程执行完毕,将其他线程中的值,返回到主线程中
        {
            print(_[0]);
            print(_[1]);
        });
    }

执行顺序
在这里插入图片描述


7

Thread —— 线程


Observable.Start() —— 开启一个线程

ObserveOnMainThread() —— 线程结果返回到主线程中,在主线程中观察
New举例子黑白88

    void Start()
    {
        var stream1 = Observable.Start(() =>
        {
            Thread.Sleep(4000);//4000毫秒
            print("等待了4秒");
            return 1;
        }); //线程1
        var stream2 = Observable.Start(() =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            print("等待2秒");
            return 2;
        }); //线程2

        
        Observable.WhenAll(stream1, stream2).ObserveOnMainThread().Subscribe(_ => //当线程执行完毕,将其他线程中的值,返回到主线程中
        {
            print(_[0]);
            print(_[1]);
        });
    }

执行顺序
在这里插入图片描述


7

Thread —— 线程


Observable.Start() —— 开启一个线程

ObserveOnMainThread() —— 线程结果返回到主线程中,在主线程中观察
New举例子黑白88

    void Start()
    {
        var stream1 = Observable.Start(() =>
        {
            Thread.Sleep(4000);//4000毫秒
            print("等待了4秒");
            return 1;
        }); //线程1
        var stream2 = Observable.Start(() =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            print("等待2秒");
            return 2;
        }); //线程2

        
        Observable.WhenAll(stream1, stream2).ObserveOnMainThread().Subscribe(_ => //当线程执行完毕,将其他线程中的值,返回到主线程中
        {
            print(_[0]);
            print(_[1]);
        });
    }

执行顺序
在这里插入图片描述


支持

May Be —— 开发者,总有一天要做的事!


拥有自己的服务器,无需再找攻略

Chinar 提供一站式《零》基础教程

使有限时间 具备无限可能!

Chinar 知你所想,予你所求!( Chinar Blog )


Chinar

END

本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com

对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值