UniRX_UniTask_学习记录_01_概述

第1章 概述

1.1 UniRx是什么

UniRx是以Reactive Extensions为基础的胃Unity的非同期和事件处理的库。

1.2 UniRx的导入方法

1.21 从 Unity Asset Store 导入

https://assetstore.unity.com/packages/tools/integration/unirx-reactive-extensions-for-unity-17276

1.22 从Github 下载最新的release包 导入

https://github.com/neuecc/UniRx

1.3 UniRx的用途

  • 非同期(异步)处理

  • 事件的处理

1.31 异步(非同期)处理
异步处理是什么

当某个处理(函数)在执行的时候,并不等到这个处理结束而去执行别的处理的这种行为叫做【异步处理】,Unity的Coroutine就是异步处理的一种。

异步处理的缺点
  • 需要对异步处理的结果进行管理

  • 能确实都将异步处理取消/中断的手段

  • 需要对执行Context(处理执行时位置和时机)进行管理

想要安全的进行异步处理,以上的一些管理手段都是必要的,UniRx则是对这些提供了这些管理手段。

异步处理和UniRx

UniRx由Observable,Operator,Scheduler这三个部分组成

| 名字 | 用途 |

| ---------- | ------------------------------------------------------ |

| Observable | 异步处理的结果和对这个处理内容的一系列流程的管理的手段 |

| Operator | Observable对复杂的处理进行辅助的手段 |

| Scheduler | Observable对执行Context进行管理的手段 |

UniRx异步处理的使用例子

    using System;

using System.Collections;

using UniRx;

using UnityEngine;

using UnityEngine.Networking;

using UnityEngine.UI;

namespace Sample.Section1

{

    public class DownloadTexture : MonoBehaviour

    {

        /// <summary>

        /// UGUI 的 RawImage

        /// </summary>

        [SerializeField] private RawImage _rawImage;

        private void Start()

        {

            //想要表示的画像的address

            var url = "https://pbs.twimg.com/media/EVAhiXWUwAQx5oD?format=jpg&name=4096x4096";



            //取得Texture

            //例外发生时 尝试3回

            GetTextureAsync(url)

                .OnErrorRetry(

                    onError: (Exception _) => { },

                    retryCount: 3

                ).Subscribe(result => { _rawImage.texture = result; },

                    error => { Debug.Log(error); })

                .AddTo(this);

        }

        /// <summary>

        /// 启动Coroutine,并把结果用 Observable返回

        /// </summary>

        /// <param name="url"></param>

        /// <returns></returns>

        private IObservable<Texture> GetTextureAsync(string url)

        {

            return Observable.FromCoroutine<Texture>(observer =>

            {

                return GetTextureCoroutine(observer, url);

            });

        }

        /// <summary>

        /// 用Coroutine进行图片下载

        /// </summary>

        /// <param name="observer"></param>

        /// <param name="url"></param>

        /// <returns></returns>

        private IEnumerator GetTextureCoroutine(IObserver<Texture> observer, string url)

        {

            using (var uwr = UnityWebRequestTexture.GetTexture(url))

            {

                yield return uwr.SendWebRequest();

                if (uwr.result == UnityWebRequest.Result.ConnectionError

                    || uwr.result == UnityWebRequest.Result.ProtocolError)

                {

                    //Error发生时 发送 OnError 消息

                    observer.OnError(new Exception(uwr.error));

                    yield break;

                }

                var result = ((DownloadHandlerTexture) uwr.downloadHandler).texture;

                //成功时 发送OnNext/OnCompleted消息

                observer.OnNext(result);

                observer.OnCompleted();

            }

        }

    }

}

GetTextureCoroutine方法,使用Coroutine对从指定的url下载Texture,并通过用UniRx(Observable) 来对不同的结果进行返回。


GetTextureCoroutine(IObserver<Texture> observer, string url)

        {

            using (var uwr = UnityWebRequestTexture.GetTexture(url))

            {

                yield return uwr.SendWebRequest();

                if (uwr.result == UnityWebRequest.Result.ConnectionError

                    || uwr.result == UnityWebRequest.Result.ProtocolError)

                {

                    //Error发生时 发送 OnError 消息

                    observer.OnError(new Exception(uwr.error));

                    yield break;

                }

                var result = ((DownloadHandlerTexture) uwr.downloadHandler).texture;

                //成功时 发送OnNext/OnCompleted消息

                observer.OnNext(result);

                observer.OnCompleted();

            }

        }

    }

}

GetTextureAsync方法,则是把Coroutine变化成Observable


        /// <summary>

        /// 启动Coroutine,并把结果用 Observable返回

        /// </summary>

        /// <param name="url"></param>

        /// <returns></returns>

        private IObservable<Texture> GetTextureAsync(string url)

        {

            return Observable.FromCoroutine<Texture>(observer =>

            {

                return GetTextureCoroutine(observer, url);

            });

        }

然后就是Start方法里,订阅由GetTextureAsync方法生成的Observable,OnErrorRetry 是 Operator中的1种,可以对出错时的处理和再处理进行指定,Subscribe()是Observable的用来接受Observable的函数,结果发行的时候,订阅的函数会被执行


        private void Start()

        {

            //想要表示的画像的address

            var url = "https://pbs.twimg.com/media/EVAhiXWUwAQx5oD?format=jpg&name=4096x4096";



            //取得Texture

            //例外发生时 尝试3回

            GetTextureAsync(url)

                .OnErrorRetry(

                    onError: (Exception _) => { },

                    retryCount: 3

                ).Subscribe(result => { _rawImage.texture = result; },

                    error => { Debug.Log(error); })

                .AddTo(this);

        }

像这样,UniRx把异步处理变成Observable,之后可以通过链式方法进行复杂的处理,和别的一步处理并行,处理结束后进行别的异步处理都可以。

和async/await比较

UniRx可以使用链式进行复杂的处理,但是简单的异步处理反而会显得很冗长,这是他的缺点,

现在 Unity可以使用C#7.3/.NET Standard2.0 的API,可以使用async/await。这个async/await 可以像同步处理一样写异步处理,所以简单的异步处理使用async/await场合更多,而不是UniRx。

UniTask

UniTask是UniRx的姐妹库一样的存在,对Unity的Async/Await进行了强化的库

上面的例子可以和UniTask并用


using System;

using System.Collections;

using System.Threading;

using Cysharp.Threading.Tasks;

using UniRx;

using UnityEngine;

using UnityEngine.Networking;

using UnityEngine.UI;

namespace Sample.Section1.Async

{

    /// <summary>

    /// 下载指定的图片

    /// 设定到rawImage

    /// </summary>

    public class DownloadTextureUniTask : MonoBehaviour

    {

        /// <summary>

        /// UGUI 的 RawImage

        /// </summary>

        [SerializeField] private RawImage _rawImage;

        private void Start()

        {

            //取得 跟这个GameObject绑定的CancellationToken

            var token = this.GetCancellationTokenOnDestroy();



            //设置图片

            SetupTextureAsync(token).Forget();

        }

        private async UniTaskVoid SetupTextureAsync(CancellationToken token)

        {

            try

            {

                //想要表示的画像的address

                var url = "https://pbs.twimg.com/media/EVAhiXWUwAQx5oD?format=jpg&name=4096x4096";

                //想要使用UniRx的Retry,把UniRX变成 IObservable

                var observable = Observable

                    .Defer(() =>

                        //UniRx -> IObservable

                        GetTextureAsync(url, token).ToObservable()).Retry(3);

                //Observable 也可以使用await 

                var texture = await observable;

                _rawImage.texture = texture;

            }

            catch (Exception e)when (!(e is OperationCanceledException))

            {

                Debug.LogError(e);

            }

        }

        //使用async/await 代替 Coroutine

        private async UniTask<Texture> GetTextureAsync(string url, CancellationToken token)

        {

            using (var uwr = UnityWebRequestTexture.GetTexture(url))

            {

                await uwr.SendWebRequest().WithCancellation(token);

                return ((DownloadHandlerTexture) uwr.downloadHandler).texture;

            }

        }       

    }

}

1.32 事件处理的利用

事件处理是当条件满足时发行事件消息,接受消息的一边会执行。

Unity开发会经常使用到各种事件。

事件处理和UniRx

UniRx提供Observable,很擅长对事件进行处理

而且Operator非常强力,复杂的事件处理可以简单的写出来。

UniRx事件处理的使用例


using System;

using UniRx;

using UniRx.Triggers;

using UnityEngine;

namespace Sample.Section1

{

    public class ThrottleButton : MonoBehaviour

    {

        private void Start()

        {

            //Update()每一帧对Fire Btn 有没有被按下进行判定

            //按下了就调用Subscribe对处理

            //然后无视30帧

            this.UpdateAsObservable()

                .Where(_ => Input.GetButtonDown("Fire1"))

                .ThrottleFirstFrame(30)

                .Subscribe(_ =>

                {

                    Debug.Log("Fire");

                });

        }

    }

}

UniRx的UpdataAsObservable() 可以把Undate()转化为Observable的消息。

ThrottleFirstFrame 是当OnNext消息发行后会停止一段时间,

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值