Unity async/await Coroutinues

c# async / await工作流可以简化你的代码,让你在Unity中对游戏有更多的控制。
学习如何转换当前协程工作流、什么是任务、如何运行顺序和同步代码以及如何从异步函数返回数据。

例子:
我们要控制三个物体在同一时间旋转以及按顺序旋转
层级视图:

相同时间旋转时,异步代码如下

using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;


public static class MyExtension
{
    public static void GetChilds(this Transform transform, List<Transform> objects)
    {
        for (int i = 0; i < transform.childCount; i++)
            objects.Add(transform.GetChild(i));
    }
}


public class AsyncManager : MonoBehaviour
{
    private List<Transform> _objects = new List<Transform>();

    private void Start()
    {
        transform.GetChilds(_objects);
        for (int i = 0; i < transform.childCount; i++)
        {
            RotateObj(i);
        }
    }
    

    private async void RotateObj(int index)
    {
        var end = Time.time + 1.5f;
        while (end - Time.time > .0f)
        {
            _objects[index].Rotate(Vector3.forward * 90 * Time.deltaTime);
            await Task.Yield();
        }
    }
}

按顺序旋转时,异步代码如下

private async void Start()
    {
        transform.GetChilds(_objects);
        for (int i = 0; i < transform.childCount; i++)
        {
            await RotateObj(i);  //等待任务执行完之后再继续执行
        }
    }
    

    private async Task RotateObj(int index)
    {
        var end = Time.time + 1.5f;
        while (end - Time.time > .0f)
        {
            _objects[index].Rotate(Vector3.forward * 90 * Time.deltaTime);
            await Task.Yield();
        }
    }

相同时间旋转时,协程代码如下

private void Start()
    {
        transform.GetChilds(_objects);
        for (int i = 0; i < transform.childCount; i++)
        {
            StartCoroutine(RotateObj(i));
        }
    }
    

    private IEnumerator RotateObj(int index)
    {
        var end = Time.time + 1.5f;
        while (end - Time.time > .0f)
        {
            _objects[index].Rotate(Vector3.forward * 90 * Time.deltaTime);
            yield return null;
        }
    }

按顺序旋转时,协程代码像下面是的

    private IEnumerator Action1()
    {
        yield return new WaitForSeconds(1);
    }
    
    private IEnumerator Action2()
    {
        yield return new WaitForSeconds(1);
    }
    
    private IEnumerator Action3()
    {
        yield return new WaitForSeconds(1);
    }
    
    private IEnumerator Sequeue()
    {
        yield return StartCoroutine(Action1());
        yield return StartCoroutine(Action2());
        yield return StartCoroutine(Action3());
    }

因为太麻烦,我们就不再对按顺序旋转时,协程进行实现

扩展:

public class AsyncManager : MonoBehaviour
{
    private List<Transform> _objects = new List<Transform>();
    private Task[] _tasks = new Task[3];

    private async void Start()
    {
        transform.GetChilds(_objects);
        for (int i = 0; i < transform.childCount; i++)
        {
            _tasks[i] = RotateObj(i);
        }

        //当列表中所有任务执行完成之后才会继续往下执行
        //代码执行顺序是对的,只是在碰上协程异步时会在刚进行时继续向下执行,因为他们并不在同一线程
        await Task.WhenAll(_tasks);
        
        Debug.Log(111);
    }

    private async Task RotateObj(int index)
    {
        var end = Time.time + 1.5f;
        while (end - Time.time > .0f)
        {
            _objects[index].Rotate(Vector3.forward * 90 * Time.deltaTime);
            await Task.Yield();
        }
    }
}
posted @ 2022-03-29 17:07  yassine  阅读(354)  评论(0编辑  收藏  举报