Unity线程与协程
文章目录
- 前言
- 一、unity真的不支持多线程吗?
- 1.unity中使用多线程
- 2.unity中多线程的停止
- 3.unity中使用多线程的问题
- 二、协同程序
- 1.协程的使用
- 2.协程的原理
- 总结
前言
Unity中的协程,即协同程序,是一个很好用的工具,我们在很多时候都会用到,但协程究竟是怎样的机制?和线程是什么样的区别?下面让我们来一探究竟。
一、unity真的不支持多线程吗?
首先,unity中是支持多线程的。初学unity时看到有些地方说,unity中不支持多线程,就没怎么尝试过。之后进一步学习时才更多的了解了一些,下面通过几个例子来看一下unity中多线程的使用。
1.unity中使用多线程
首先在unity场景中创建一个空物体,创建一个新的C#脚本,在类中定义一个方法,循环打印1,再定义一个线程对象,在Start()生命周期函数中开启线程。
代码如下:
Thread t;// Start is called before the first frame updatevoid Start(){t = new Thread(Test);t.Start();}void Test(){while (true){print(1);}}
将脚本挂载到场景上的空物体,运行,发现可以正常打印出1,也没有报错。
2.unity中多线程的停止
如果做到了这一步,接下来会发现,即使停止运行,程序仍在继续打印1。尝试将线程对象改为后台线程,重新运行:
代码如下:
t.IsBackground = true;
发现仍然不停打印。原因,其实UnityEditor本身就是这个软件程序中的一根线程,当我们在脚本中新开一个线程时,它是和UnityEditor同步执行的,所以我们停止了UnityEditor的运行并不会影响这个线程的执行。解决方案:在脚本的生命周期函数OnDestory()中停止线程,这样停止运行时会调用场景上对象的OnDestory()方法,就会停止其它线程。
代码如下:
void OnDestroy(){t.Abort();}
3.unity中使用多线程的问题
下面我们再通过一个例子看一下,为什么有unity中不支持多线程的这种说法。还是上述脚本,我们改一下Test方法:
代码如下:
Thread t;// Start is called before the first frame updatevoid Start(){t = new Thread(Test);t.Start();}void Test(){while (true){print(transform.position);}}
注意这里将打印结果改为了transform.position,运行,发现报了这样一个错误:
提示get_transform是Component类中的一个属性中的get方法,涉及到unity中的一些反射机制,这里不做过多描述,简单来说提示的意思就是我们要打印的transform.position只能在主线程中执行。实际上我们在脚本中新开的线程无法访问绝大部分unity中的对象,都会报这个错误,所以会有unity不支持多线程的这种说法,但实际上这种说法并不完全正确。
虽然新开的线程无法访问unity中的很多对象,但是我们可以将一些复杂的算法计算、网络连接等逻辑抛给一个新的线程去处理,将处理的数据放在公共内存模块中,在unity主线程就可以访问使用了,关于这种案例我们之后再讨论,前面说了很多关于多线程的问题,下面来讲一下unity对于以上问题机制给出的解决方案——协程。
二、协同程序
协同程序简称协程,多在资源、场景异步加载等逻辑时使用,它的使用效果和线程有些类似,都可以在不卡住主程序的情况下开启另一段逻辑的执行,但是它和线程有本质上的区别,协程的执行是在主线程下,而不是在另一个线程中,所以它可以访问unity中的所有对象,而不会出现上述使用线程中遇到的问题。
1.协程的使用
协程的基本使用:声明一个返回值为IEnumerator的方法,用然后用MonoBehaviour中的StartCoroutine()方法开启协程。
代码如下:
void Start(){//开启协程返回一个协程对象Coroutine co = StartCoroutine(Test());//关闭协程StopCoroutine(co);}IEnumerator Test(){while (true){print(1);//要有一个yield修饰的返回值yield return new WaitForSeconds(1);}}
协程方法是每秒钟打印一次1,这里关于协程的返回值暂时不做过多介绍,之后可能在别的文章中具体说明,读者也可看一下unity官方的描述,下面着重讲一下协程原理。
2.协程的原理
协程本质上包括两部分:
1、协程方法
2、协程调度器
协程方法即返回值为IEnumerator接口类型或其子类的方法,本质上是一个迭代器方法,不了解C#迭代器的读者可以先补充一下这方面的知识。我们进入IEnumerator接口看一下:
public interface IEnumerator{//表示方法当前执行到的返回值object Current { get; }//继续执行方法,返回表示是否执行完毕bool MoveNext();//重置方法的执行位置void Reset();}
我们不使用MonoBehaviour的StartCoroutine方法,来执行一个协程:
代码如下:
void Start(){IEnumerator ie = Test();print(ie.MoveNext());print(ie.Current);print(ie.MoveNext());print(ie.Current);print(ie.MoveNext());print(ie.Current);print(ie.MoveNext());print(ie.Current);}IEnumerator Test(){print(1);yield return 1;print(2);yield return "哈哈";print(3);yield return 3.14;print(4);yield return gameObject;}
unity中的运行结果:
由此可见,所谓协同程序,就是一步步的执行迭代器对象中的MoveNext()方法,调用MoveNext()方法会执行下一个yield return之前的逻辑,并且根据MoveNext()的返回值判断是否全部执行完毕,而通过yield return返回Current成员对象,来判断下一次执行MoveNext()的时机。而这些工作,就是由协同程序的第二部分——协程调度器来实现的。这里的协程调度器是unity引擎实现的,理论上我们是可以自己去实现一个协程调度器的,大家感兴趣的话可以自己实现一个,能进一步加深对协程的理解。
总结
总之,协同程序的存在很大程度上弥补了unity中使用多线程出现的问题,但在原理上与线程有本质上的区别,我们在使用时也要依据情景,选择更适合的方式。另外,文章中并没有过多的阐述协程的使用,如果读者没有这部分的基础需要自己学习一下,之后可能会单独发一篇文章来详细描述协程的使用。
Unity线程与协程相关推荐
- Unity C#笔记 协程详解(转)
目录 什么是协程 多线程 协程 协程的使用场景 协程使用示例 Invoke的缺陷 协程语法 开启协程 终止协程 挂起 协程的执行原理 什么是协程 在Unity中,协程(Coroutines)的形式是我 ...
- unity如何解决协程开启频繁导致的程序卡顿
unity如何解决协程开启频繁导致的程序卡顿 一.协程 协程并不会在Unity中开辟新的线程来执行,其执行仍然发生在主线程中.当我们有较为耗时的操作时,可以将该操作分散到几帧或者几秒内完成,而不用在一 ...
- 进程 线程 协程_进程,线程,协程那些事
无论我们写出怎样的程序,最后都是由操作系统来运行我们的程序,而操作系统如何管理我们的程序,我们程序的数据如何保存和计算,这些都是操作系统需要处理的事情,我们只要将写好的程序交给操作系统就好. 虽然操作 ...
- python 多线程和协程结合_一文讲透 “进程、线程、协程”
本文从操作系统原理出发结合代码实践讲解了以下内容: 什么是进程,线程和协程? 它们之间的关系是什么? 为什么说Python中的多线程是伪多线程? 不同的应用场景该如何选择技术方案? ... 什么是进程 ...
- 进程、线程、协程、通信方式
文章目录 进程 线程 协程 进程.线程.协程的区别 概念 进程.线程共同点 进程.线程不同点 线程.协程比较 通信方式之间的差异 进程通信 管道(pipe) 有名管道 (namedpipe) 信号量( ...
- 打开线程 | 进程 | 协程的大门
不知从几何起,可能是大三那年的操作系统考试,也可能是刚经历完的秋招,这些概念总是迷迷糊糊,可能自己回答的和其他人的答复也差不多,并没有什么亮点,通常都会以:「我们换个题」的方式结束,有时候也挺尴尬的. ...
- 线程,协程对比和Python爬虫实战说明
此文首发于我的个人博客:线程,协程对比和Python爬虫实战说明 - zhang0peter的个人博客 这篇文章写的是我对线程和协程的理解,有错误之处欢迎指出. 举一个餐馆的例子.我们把一个餐厅当做一 ...
- 什么是 “进程、线程、协程”?
作者 | 头文件 责编 | 王晓曼 来源 | 程序员小灰(ID:chengxuyuanxiaohui) 本文从操作系统原理出发结合代码实践讲解了以下内容: 什么是进程,线程和协程? 它们之间的关系是什 ...
- Kotlin极简教程:第9章 轻量级线程:协程
原文链接:https://github.com/EasyKotlin 在常用的并发模型中,多进程.多线程.分布式是最普遍的,不过近些年来逐渐有一些语言以first-class或者library的形式提 ...
最新文章
- UIActivityViewController使用
- 7-1 抓老鼠啊~亏了还是赚了? (20 分)
- 收藏 | 使用Pytorch从头实现Canny边缘检测
- tensorflow 遇到的细节问题
- Spring.Net配置多数据源
- oracle mysql数据库管理工具下载_Oracle数据库管理工具PC版-Oracle数据库管理工具下载v15.0.21.0(32/64)-IE浏览器中文网站...
- 黑苹果无线网卡选择intel还是博通?及其驱动方式详解
- rtt segger 低功耗模式_Segger RTT使用注意事项
- 普及ERP不靠低价风暴(转)
- 夜神模拟器-软件apk存放目录
- Java生成随机数字和字母组合10位数
- python根据excel生成报表_python生成Excel图表(通过xlsxwriter)
- 秒针计时器 html,js实现秒表计时器
- 一段神奇的代码-关于PHP字符变量奇怪现象的解释
- 非root用户执行程序---sudo的使用
- BNUZ程协技术部2020寒假任务简单版(后端)
- Spring学习第4篇:Spring 的依赖注入
- vi 跳到文件最后一行
- IBM通过云端让量子计算机变得唾手可得
- Synchro Arts的软件正式支持Apple Silicon(M1)
热门文章
- 人工智能小白日记 语音情感分析探索之2 CNN相关及实验
- 互联网经典SQL面试题及答案解析
- Scala+Hadoop+Spark开发
- Redis架构设计实现
- DSP TMS320F280049C——互补波形(一)
- javaScript用函数的方法判断素数:判断一个数是否是素数(代码)
- 2003计算机应用基础题答案,计算机应用基础(Windows_XP+Office_2003)课后题答案
- python数据拟合固定参数_固定某些参数的双峰高斯分布拟合
- 解决Qt5屏幕翻转问题
- 爬虫实战——求是网周刊文章爬取