深入理解协程

Unity中的协程:概念、使用与优化
本文介绍了Unity中的协程,包括它的概念、如何创建和使用协程,以及协程在游戏开发中的应用场景。通过示例展示了协程如何实现延迟执行和简化复杂流程,特别强调了在Unity中协程如何处理网络请求和资源管理。同时,讨论了协程的效率问题,指出协程不会提高程序运行速度,但能提高开发效率。最后,探讨了协程是否能替代Update以及协程设计思想。

简述

想一想我们平时购买电脑提及的,cpu是四核八线程,其实cpu原先只能处理处理一件事,也就是说cpu默认是一个核心对应一条线程的,但是如果我们需要同时处理多个任务,而我们并没有那么多的线程数量。 然后前人们就提出了虚拟线程的概念,将cpu的单个线程,虚拟出多条线程,也就有了我们四核八线程,八核十六线程等的概念;在应用程序这边也有了线程和进程的概念,在把进程再细分,虚拟化软件的线程就得到了协程的概念。
至此你知道,协程就是对线程的再细分,是线程的再虚拟化即可。

unity的协程

虽然说协程的概念并不新颖,但在现在大趋势的互联网开发领域可能很少涉及到协程这个词汇。 协程就是协力去完成一件事,这很容易想到多线程的概念,例如我们进行一次网络请求我们需要等待response之后才能下一步操作,此时我们就会用到互斥锁、线程安全等概念。 在unity中或者说在游戏引擎中,由于受到游戏主循环线程的制约,所以不能确保多线程的安全性,此时在同一线程下继续使用协程来承担多线程的工作就显得尤为重要。 (unity也退出了以性能优先的ECS模式,摒弃Mono框架,实现了可多线程协助开发的开发模式) 下面我们就主要以unity的协程详细介绍。

unity协程示例

看这个例子:
//创建协程 private IEnumerator Cor1() { yield return new WaitForSeconds(2f); Debug.Log("2s到了"); } //启动协程 StartCoroutine(Cor1());
这是一个简单示例,可以看到协程需要返回一个IEnumerator可迭代对象,这本来是Csharp中的迭代器模式的实现,在unity中unity以此为原型实现了协程。

协程的参数

在上面我们使用了 new WaitForSeconds(),这表示等待指定的时间。【注意WaitForSeconds与Time.Scale相关】 在上面使用的WaitForSeconds之外还有许多的参数,这些参数要么需要花费时间,要么返回bool,总之就是需要确定一个moveNext。

协程的使用情况

  1. 用于不确定的时长情况(例如:网络请求,读写文件)
  2. 用于延迟执行
  3. 可当做简易计时器使用(例如:生产一批敌人)

协程的嵌套

协程支持嵌套,如下是一个利用协程实现的巡逻的简单实现。 注:在unity中,协程返回0或null表示等待下一帧。
using System; using System.Collections; using UnityEngine; namespace Coroutines { //协程测试 public class CoroutTest : MonoBehaviour { public Transform[] wayPoints; private bool isLoop; private void Start() { isLoop = true; StartCoroutine(StartLoop()); } private IEnumerator StartLoop() { do { foreach (var point in wayPoints) { yield return StartCoroutine(MoveTarget(point.position)); } } while (isLoop); } private IEnumerator MoveTarget(Vector3 target) { while (transform.position!=target) { transform.position = Vector3.MoveTowards(transform.position, target, 3 * Time.deltaTime); yield return 0; } } } }

让协程动起来

  • StartCoroutine(nameof(StartLoop)); 以字符串形式启动协程,能够在外部停止协程,无法传递参数。
  • StartCoroutine(StartLoop); 以迭代器形式启动协程,能够传递参数,无法在外部使用stop停止协程。

让协程停下来

协程本质是一个迭代器,当moveNext为false时即认为协程中所有的项目都已经执行完毕。 在unity中有以下几种方式停止协程:
  1. StopCoroutine() 注意此方式只能停止以字符串形式启动的协程 【在协程外部使用】
  2. yield break 跳出协程【在协程内部使用】
  3. 通过逻辑来停止 【使其协程执行条件不满足】
  4. 设置物体不激活 【再次激活协程也不会恢复】
  5. StopAllCoroutine() 终止所有协程
如上面协程嵌套的例子中,如果我们想要协程停止:
  1. 设置isLoop=false;让其在执行一次后不满足条件自动停下
  2. 在协程内部break
if (transform.position==wayPoints[2].position) { yield break; }
  1. 在协程外部 stop
StopCoroutine(nameof(StartLoop));

协程的设计思想

协程是否取代update?
通过上面的例子,你大可发现,协程其实是对update的另一种实现,我们甚至可以只使用协程而不使用任何update和fixedUpdate完成程序的编写。 但我们如果这样做不是本末倒置了吗?协程是unity推出的延迟执行的一种范式,其还是基于update为原理的上层实现。
使用协程会大大提升程序效率吗?
不会,协程本质上还是在一条线程上,尽管可以多条协程并行,但这些协程始终还是运行在一条线程上,速度和效率并不会得到很大的提升。反而开辟多条线程并行,线程需要多多协程的状态保持监听,在协程大量结束时会触发大量GC 回收,可能会降低程序的运行效率。

总结

协程是运行在线程上的线程,其运作方式任然基于单线程,并不会因为使用协程提高程序的运行效率,但协程方便的书写方式,强大的功能能够提高我们作为开发者的开发效率。 从某种意义上来讲,协程更像是一个精美的语法糖
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值