Unity多线程
unity支持多线程。且线程开启方式与C#中一样。不过子线程无法访问Unity相关对象的内容!包括物体,transform,哪怕Unity的Random都不行。另外子线程需要手动关闭!!!
public class Test : MonoBehaviour
{
private Thread thread;
private void Start()
{
thread = new Thread(() =>
{
while (true)
{
print(123);
Thread.Sleep(1000);
}
});
//开启线程
thread.Start();
}
private void OnDestroy()
{
//关闭线程
thread.Abort();
}
}
所以,一般子线程都会被用来做一些耗时的运算,比如A*寻路,网络请求等。当子线程运算结束后,可以将结果放到一个公共内存区,比如一个队列,然后主线程就可以去队列里面获取数据了。
协同程序
不是多线程。
作用:
- 将代码分时分步执行,不卡主线程。简单的理解就是把可能会让主线程卡顿的耗时逻辑分时分步的执行。
主要使用场景:
- 异步加载文件
- 异步下载文件
- 场景异步加载
- 批量创建时防止卡顿
协程和多线程的区别
多线程:新开一个线程时独立的一个管道,和主线程并行执行。
协程:新开一个协程是在主线程上开启,进行逻辑的分时分步执行。本质上只有一个线程。
详细来讲就是:协程函数是在原线程上开启的(一般都是主线程),会将耗时的逻辑分成N个步骤去执行,每次只执行一个步骤,然后会有返回值(决定了什么时候,是否继续下一个步骤),然后协程挂起,主线程继续执行。因为主线程是一个死循环,他会有自己的生命周期函数,所以在上个步骤执行完之后的下一帧,会根据上一个步骤的返回值去判断是否继续执行下一个步骤。同时在执行每个步骤时都可以控制等待时间,即加Delay函数。直到所有步骤执行完。
协程的使用
继承MonoBehavior的类都可以开启协程函数。
第一步:申明协程函数。协程函数 有两个关键点:1.返回值为IEnumerator类型及其子类;2.函数中通过yield return返回值进行返回。
IEnumerator Test1()
{
//这里的协程函数分为了2步,第一步是打印1,然后等待1帧,打印2。
//第一步
print(1);
yield return 1;
//第二步
print(2);
yield return 2;
}
第二步:开启协程函数。
//协程函数是不能狗执行调函数执行的!
//Test1();
//常用的开启方式
StartCoroutine(Test1());
关闭协程
var cor = StartCoroutine(Test1());
//关闭指定协程
StopCoroutine(cor);
//关闭所有协程
StopAllCoroutines();
yield return返回值类型
决定下一步什么时候执行
- 下一帧执行:yield return 数字或null。会在update和LateUpdate之间执行
- 等待指定秒后执行:yield return new WaitForSeconds(秒)
- 等待下一个固定物理帧更新时执行:yield return new WaitForFixedUpdate()。将在FixedUpdate和碰撞检测相关函数之后执行。
- 等待摄像机和GUI渲染完成后执行:yield return new WaitForEndOfFrame()。在LastUpdate之后的渲染相关处理完毕后执行。
- 一些特殊类型的对象,比如异步加载相关函数的返回对象。会在资源加载完毕之后执行。一般在Update和LateUpdate之间执行。
- 跳出协程:yield break;
协程受对象和组件失活销毁的影响
协程开启后,组件和物体销毁,协程不执行;物体失活协程不执行;组件失活协程执行。
在异步加载场景时会受影响,因为异步加载场景完成后会销毁当前场景,导致当前场景的协程后续不执行。
总结
- Unity支持多线程,只是新开线程无法访问主线程的Unity相关内容。一般主要进行复杂的逻辑运算或网络消息接收等!注意:Unity中的多线程一定要记住关闭!
- 协同程序不是多线程,他是将线程中的逻辑进行分时执行,避免卡顿。
- 继承MonoBehavior的类都可以开启协程函数
- 开启/关闭协程的方法
- yield return返回的内容的含义
- 协程只有当组件单独失活时不受影响,其他情况(物体失活/销毁,组件销毁)协程都会停止