首先

我们将在名为 Studio Shimazu 的 Unity 在线社区举行学习会议。
该文件将是 UniTask 的简要总结。

目录

  • 关于同步
  • 关于异步处理
  • 协程审查
  • 关于等待/异步
  • 关于线程
  • UniTask 的不幸之处
  • 结论

关于同步

执行多个进程时,进程按顺序一一执行

@Sample01
using UnityEngine;

// ======================================================================
// 同期処理について
// ======================================================================
public class Sample01 : MonoBehaviour
{
    void Start()
    {
        A();
    }

    void A()
    {
        Debug.Log("A");
        B();
        Debug.Log("C");
    }

    void B()
    {
        Debug.Log("B");
    }
}

执行结果为 A → B → C

图示时是这样的
とりあえずUniTask学んでみたのでまとめてみる

关于异步处理

执行多个进程时,进程在执行结果之前返回

@Sample02
using System.Collections;
using UnityEngine;

// ======================================================================
// 非同期処理
// ======================================================================
public class Sample02 : MonoBehaviour
{
    void Start()
    {
        A();
    }

    void A()
    {
        Debug.Log("A");
        StartCoroutine(B());
        Debug.Log("C");
    }

    IEnumerator B()
    {
        yield return new WaitForSeconds(1);
        Debug.Log("B");
    }
}

执行结果为 A → C → B
图示时是这样的
とりあえずUniTask学んでみたのでまとめてみる

协程审查

@Sample03
using System.Collections;
using UnityEngine;


// ======================================================================
// コルーチンの復習
// ======================================================================
public class Sample03 : MonoBehaviour
{
    void Start()
    {
        StartCoroutine(SampleCoroutine());
    }

    IEnumerator SampleCoroutine()
    {
        Debug.Log("スタート");

        // 2秒待機する
        yield return new WaitForSeconds(2f);

        Debug.Log("ゴール");
    }
}

有了这种感觉,2秒后就可以像〇〇那样处理了。

协程也有缺点,

  • 函数不能有返回值(严格来说可以)
  • 除非继承了 MonoBehaviour,否则无法使用
  • 当游戏对象被销毁或隐藏时处理停止

等等。

关于等待/异步

await/acync 是 C# 中的异步处理函数。

不像协程,它可以有一个返回值,
它可以在没有 MonoBehaviour 的情况下使用。
但是,由于即使游戏对象被破坏它也会移动,
你应该小心。 (稍后会解释。)

@Sample04
using UnityEngine;
using Cysharp.Threading.Tasks;
using System;


// ======================================================================
// お試しUniTask
// ======================================================================
public class Sample04
{
    async void Start()
    {
        await Test();
    }

    async UniTask Test()
    {
        Debug.Log("スタート");

        // 2秒待機する
        await UniTask.Delay(TimeSpan.FromSeconds(2));

        Debug.Log("ゴール");
    }
}

用 await/async 替换协程如下所示:

@Sample05

using UnityEngine;

// ======================================================================
// お試しUniTaskその2
// ======================================================================
public class Sample05 : MonoBehaviour
{
    async void Start()
    {
        Sample05_2 sample05_2 = new Sample05_2();

        // Test()がreturnするまで待機する
        var str = await sample05_2.Test();
        Debug.Log(str);
    }
}

using System;
using Cysharp.Threading.Tasks;
using UnityEngine;

public class Sample05_2
{
    public async UniTask<string> Test()
    {
        Debug.Log("スタート");

        // 2秒待機する
        await UniTask.Delay(TimeSpan.FromSeconds(2));

        return "ゴール";
    }
}

这就是返回值的样子。

顺便一提,

var str = await sample05_2.Test();

await 表示等待直到进程完成。
如果不写这个await,“str”会输出为空。

关于线程

线程意味着在运行程序时
让它作为多线程处理,
它可以作为单线程处理。

以游戏制作为例,
在游戏中进行计算的过程和
我认为有一个为游戏绘制图形的过程。
如果您通常使用 Unity 进行生产,则使用单线程
由于这两个进程同时运行,
如果计算过程变得复杂,它就会变得繁重。

因此,让我们让另一个线程来做计算部分!
你可以像这样使用它

详细的我就不写了,不过C#本来就有一个线程处理函数叫Task。
它在 Unity 中是一个难以使用的功能,但 UniTask 使它易于使用。
变得。

@Sample06
using System.Threading;
using Cysharp.Threading.Tasks;
using UnityEngine;


// ======================================================================
// お試しスレッド処理
// ======================================================================
public class Sample06 : MonoBehaviour
{
   async void Start()
    {
        Debug.Log(Thread.CurrentThread.ManagedThreadId);
        
        // 処理するスレッドの変更
        await UniTask.SwitchToThreadPool();
        
        Debug.Log(Thread.CurrentThread.ManagedThreadId);

        // 処理するスレッドをメインスレッドに変更
        await UniTask.SwitchToMainThread();
        
        Debug.Log(Thread.CurrentThread.ManagedThreadId);
    }


}

这很容易,但这是切换处理线程。

实际上,如果它不是主线程,Unity的标准变换等。
不能用,不过这次就简单介绍一下。

UniTask 的麻烦部分

最后总结一下UniTask比较麻烦的地方。
以至于我想知道是否可以因此使用协程进行个人开发。

如上所述,即使 GameObject 被销毁,UniTask 进程也会继续进行。
因此,如果要在销毁时停止处理,则必须自己编写该处理。

这一次,如果您左键单击,则销毁您自己的游戏对象并执行该过程。
编写代码停止

@Sample07
using UnityEngine;
using Cysharp.Threading.Tasks; // UniTaskに必要
using System.Threading; // CancelToken系に必要
using System;


// ======================================================================
// お試し中断処理
// ======================================================================
public class Sample07 : MonoBehaviour
{
    private CancellationTokenSource _cts = new CancellationTokenSource();

    async void Start()
    {
        Debug.Log("Start");

        // トークンソースからトークンを生成
        CancellationToken token = _cts.Token;

        // 非同期が止まったときの例外を書かないとエラーになる
        try
        {
            await A(token);
        }
        catch (OperationCanceledException)
        {
            Debug.Log("処理を強制的に終わらせたよ");
        }
    }

    // 5秒待機するUniTask
    async UniTask A(CancellationToken token)
    {
        await UniTask.Delay(5000, false, PlayerLoopTiming.Update, token);
        Debug.Log("待てたよ");
    }

    void Update()
    {
        // クリックしたらキャンセル
        if (Input.GetMouseButtonDown(0))
        {
            Destroy(gameObject);
        }
    }

    // gameobject破壊時にメモリの開放
    void OnDestroy()
    {
        _cts.Cancel();
        _cts.Dispose();
    }
}

我对它不是很熟悉,但是我通常不会使用 Dispose() 来释放内存,
你必须编写个人开发中不经常使用的流程,例如try-catch语句中的异常处理。

相反,如果你想研究这样的 C# 函数,最好在 UniTask 上工作。
是不是。

综上所述

我整理了一份学习材料清单。
如果有任何错误,我很抱歉。
如果你能到时候告诉我会很有帮助!


原创声明:本文系作者授权爱码网发表,未经许可,不得转载;

原文地址:https://www.likecs.com/show-308632068.html

相关文章:

  • 2021-08-16
  • 2021-07-04
  • 2022-12-23
  • 2021-07-04
  • 2022-12-23
  • 2021-06-14
  • 2021-11-21
  • 2022-01-20
猜你喜欢
  • 2021-11-17
  • 2021-08-31
  • 2021-10-14
  • 2022-02-04
  • 2022-12-23
  • 2022-12-23
  • 2021-10-07
相关资源
相似解决方案