在之前 Unity 想要实现延迟执行或者是等待,要么只能使用自己计数的方法,要么使用协程。
# Ep.1 协程
首先让我们来看一个协程示例:
示例是循环 10 次,每次等待 0.2s。
IEnumerator Func() | |
{ | |
for (int i = 0; i < 10; i++) | |
{ | |
print(i); | |
yield return new WaitForSeconds(0.2f); | |
} | |
} | |
// 启动协程 | |
StartCoroutine(Func()); |
# Ep.2 Async 异步
Async 异步的概念是微软基于多线程提出的 Task 解决方案,相比传统多线程具有很多优势。
- ❤️相比协程来说,异步的方式不需要搭建基础的协程框架(
不需要新创建一个方法
),可以直接在方法中使用关键字实现等待。 - 不需要启动
async void AsyncFunc() | |
{ | |
for (int i = 0; i < 10; i++) | |
{ | |
print(i); | |
await Task.Delay(100); | |
} | |
} |
# Ep.3 解决痛点
其实 async 还有其他的优势,让我们来看看这些例子😺
# 协程队列
🌓 有时我们需要这样一种情况,需要在 A 执行结束后执行 B,B 执行结束后执行 C。
# 协程解决方案
可以看到,通用的解决方案需要创建多个协程方法,并创建一个总协程方法来为所有参与协程进行排序。
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执行结束!"); | |
} |
# 异步解决方案
按照协程的思路我们可以这样来替换。
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"); | |
} |
# 特殊使用
# 持续执行
可以使用如下的方式来持续执行一系列的动作!😏
async Task Rote(float endTime, Vector3 dir) | |
{ | |
while (Time.time < endTime) | |
{ | |
transform.position += dir; | |
// 线程让步,让线程池重新排 | |
await Task.Yield(); | |
} | |
print("执行完成"); | |
} |
# 多任务并行
可以为 Start 方式设定异步 Async
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 的特性使用出来。
✔️同时,Unity 再也不是虚假的多线程了!