Async代替协程

在之前Unity想要实现延迟执行或者是等待,要么只能使用自己计数的方法,要么使用协程。

Ep.1 协程

首先让我们来看一个协程示例:

示例是循环10次,每次等待0.2s。

协程示例
1
2
3
4
5
6
7
8
9
10
11
IEnumerator Func()
{
for (int i = 0; i < 10; i++)
{
print(i);
yield return new WaitForSeconds(0.2f);
}
}

//启动协程
StartCoroutine(Func());

Ep.2 Async 异步

Async异步的概念是微软基于多线程提出的Task解决方案,相比传统多线程具有很多优势。

  • :heart:相比协程来说,异步的方式不需要搭建基础的协程框架(不需要新创建一个方法),可以直接在方法中使用关键字实现等待。
  • 不需要启动
Async示例
1
2
3
4
5
6
7
8
async void AsyncFunc()
{
for (int i = 0; i < 10; i++)
{
print(i);
await Task.Delay(100);
}
}

Ep.3 解决痛点

其实async还有其他的优势,让我们来看看这些例子:smiley_cat:

协程队列

:first_quarter_moon: 有时我们需要这样一种情况,需要在A执行结束后执行B,B执行结束后执行C。

协程解决方案

可以看到,通用的解决方案需要创建多个协程方法,并创建一个总协程方法来为所有参与协程进行排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
IEnumerator FunAll()
{
yield return FunA();
yield return FunB();
yield return FunC();
print("全部执行结束!");
}


IEnumerator FunA()
{
yield return new WaitForSeconds(1f);
print("A执行结束!");
}

IEnumerator FunB()
{
yield return new WaitForSeconds(1f);
print("B执行结束!");
}

IEnumerator FunC()
{
yield return new WaitForSeconds(2f);
print("C执行结束!");
}

异步解决方案

按照协程的思路我们可以这样来替换。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private async void Run()
{
await Fun1();
await Fun2();
print("FunEnd");
}

private async Task Fun1()
{
await Task.Delay(2000);
print("Fun1");
}
private async Task Fun2()
{
await Task.Delay(2000);
print("Fun2");
}

特殊使用

持续执行

可以使用如下的方式来持续执行一系列的动作!:smirk:

1
2
3
4
5
6
7
8
9
10
11
async Task Rote(float endTime, Vector3 dir)
{
while (Time.time < endTime)
{
transform.position += dir;
//线程让步,让线程池重新排
await Task.Yield();
}

print("执行完成");
}

多任务并行

可以为Start方式设定异步Async

1
2
3
4
5
6
7
8
9
10
11
private async void Start()
{
var tasks=new List<Task>();
for (int i = 0; i < 3; i++)
{
//异步启动多个Task任务
tasks.Add(Fun1());
}
await Task.WhenAll(tasks);
print("全部执行完");
}

Ep.4 总结

使用这样Async方式,大大简化了协程的使用复杂度,简化了代码数量,重要的是可以将一些Task的特性使用出来。

:heavy_check_mark:同时,Unity再也不是虚假的多线程了!