Unity Async & Coroutines 学习笔记

起因

最近在油管上看到了一个关于Async 和 Coroutines的对比,刚好中间有一个例子,使用Async解决双指同时点击两个不同的Button,会触发两段逻辑的Bug,而且整段代码写起来非常快乐

优缺点对比

返回值功能对比

同步功能对比

try catch 功能对比

调用堆栈功能对比

Exception 隐藏功能对比

exit 功能对比

生命周期对比

Coroutine 的生命周期取决于MonoBehavior
Async 的声明周期需要手动控制

所以引出了Cancel Task的逻辑

需要注意的是在还没有执行到Cancel的时候,这个GameObject 被销毁了,这个时候依然无法取消

PopUp Window 例子

效果展示

这里没有做窗口,只是单纯展示逻辑

  • 点击Test 开启监听,之后点击Accept返回True,点击Cancel或X,返回False
  • 点击Test 开启监听,之后点击CancelTest,取消刚刚的Task
  • 无论执行结果是什么,或者取消,都会输出Finally

视频中的例子还包含返回的Button,这里的例子就不包含这个部分了

2019-10-05 at 11.45 P

UI Async 代码

利用Async 可以天然解决掉双指触摸Button的Bug,之前需要写一堆控制,非常不快乐

下面的代码用来举例说明具体调用,在项目中还需要另外调整

public class AsyncTest : MonoBehaviour {
    public Button ButtonAccept;
    public Button ButtonCancel;
    public Button ButtonClose;
    private CancellationTokenSource cts;

    public async Task<bool> Spawn(CancellationToken ct) {
        using(var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(ct)){
            try{
                CancellationToken linkedCt   = linkedCts.Token;
                var               buttonTask = Utils.SelectButton(linkedCt, ButtonAccept, ButtonCancel, ButtonClose);
                await buttonTask;
                linkedCts.Cancel();

                return buttonTask.Result == ButtonAccept;
            }
            catch(OperationCanceledException e){
                Debug.Log("Cancel Operation");
                return false;
            }
            finally{
                linkedCts.Dispose();
                Debug.Log("Finally");
            }
        }
    }


    public async void TestButton() {
        cts = new CancellationTokenSource();
        bool result = await Spawn(cts.Token);

        Debug.Log(result);
    }

    public void CancelTestButton() {
        cts.Cancel();
        Debug.Log("Cancel");
    }
}

public static class Utils {
    public static async Task<Button> SelectButton(CancellationToken ct, Button accept, Button cancel, Button close) {
        bool   isSelect    = false;
        Button selectedBtn = null;

        accept.onClick.AddListener(
            () => {
                isSelect    = true;
                selectedBtn = accept;
            }
        );

        cancel.onClick.AddListener(
            () => {
                isSelect    = true;
                selectedBtn = cancel;
            }
        );

        close.onClick.AddListener(
            () => {
                isSelect    = true;
                selectedBtn = close;
            }
        );

        return await Task.Run(
            () => {
                while(true){
                    if(ct.IsCancellationRequested) ct.ThrowIfCancellationRequested();
                    if(isSelect) return selectedBtn;
                }
            },
            ct
        );
    }
}

视频参考

Best practices: Async vs. coroutines – Unite Copenhagen

作者:L
本文采用 CC BY-NC-SA 4.0 协议

评论

  1. 秒大刀
    8月前
    2022-8-05 16:12:22

    写的很仔细,对我帮助很大。而且页面布局美观,排版用心。感谢!~

    • 博主
      秒大刀
      8月前
      2022-8-05 17:18:03

      有帮助就好~

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇