Unity支持多线程
但新开的线程无法访问Unity对象的相关内容
多线程记得要关闭,不然线程与编辑器共生,一直存在
public class cor : MonoBehaviour
{
Thread t1;
// t1就无法访问本脚本所挂载的GameObject的相关内容
void Start()
{
t1 = new Thread(Test);
t1.Start();
}
private void Test()
{
while (true)
{
//this.transform.Translate(Vector3.forward * Time.deltaTime);运行时会报错,访问对象必须从主线程访问
print("123");
Thread.Sleep(1000);
}
}
//生命周期结束时关闭线程
private void OnDestroy()
{
t1.Abort();
t1 = null;
}
}
多线程作用:在副线程中进行一些复杂运算,防止主线程卡主,例如:
public class cor : MonoBehaviour
{
Thread t1;
Queue<Vector3> queue = new Queue<Vector3>();
void Start()
{
t1 = new Thread(Test);
t1.Start();
}
private void Update()
{
if(queue.Count > 0)
{
this.transform.position = queue.Dequeue();
}
}
private void Test()
{
while (true)
{
Thread.Sleep(1000);
System.Random r = new System.Random();
//模拟复杂算法算出结果放入公共容器中
queue.Enqueue(new Vector3(r.Next(-10,10), r.Next(-10, 10), r.Next(-10, 10)));//不能直接使用Unity中的Random
}
}
//生命周期结束时关闭线程
private void OnDestroy()
{
t1.Abort();
t1 = null;
}
}
协同程序(协程)是什么
是“假的”多线程,不是多线程,将代码分时执行,不卡主线程,即把可能会导致主线程卡顿的逻辑分时分步执行
主要用于:
异步加载文件、异步下载文件、场景异步加载、批量创建时防止卡顿
协程与线程的区别
新开一个线程是独立的一个管道,和主线程并行执行
新开一个协程是在原线程之上开启,进行逻辑分时分步执行,即将一个函数拆成多个部分,每执行一步会将剩余部分挂起,因为Unity程序本身为死循环,后续循环才执行协程中未执行的代码,也就是说该函数每一个步骤的执行最少需要等待一帧的时间。
协程的使用
继承Mono的类都可以开启协程函数
void Start()
{
t1 = new Thread(Test);
//t1.Start();
//协程函数不能直接这样执行,这样执行没有任何效果
//MyCoroutine(1, "123");
//正确执行方法
Coroutine c1 = StartCoroutine(MyCoroutine(2, "123"));
//或者
IEnumerator ie = MyCoroutine(2, "123");
StartCoroutine(ie);
//关闭协程
//关闭所有协程
StopAllCoroutines();
//关闭指定协程
StopCoroutine(c1 );
}
IEnumerator MyCoroutine(int i, string str)
{
print(i);
//协程函数中必须使用 yield return进行返回
yield return new WaitForSeconds(5f);
print(str);
yield return new WaitForSeconds(5f);
print("12334213");
yield return new WaitForSeconds(5f);
print("123342");
while(true)
{
print("5");
yield return new WaitForSeconds(5f);
}
}
yield return 不同内容的含义
协程开启后
组件或物体销毁协程不执行
物体失活协程不执行,组件失活协程执行
协程原理
协程函数本体如果不通过开启协程方法执行协程,Unity协程调度器不会帮助我们管理协程函数。
手动执行
IEnumerator ie = MyCoroutine(2, "123");
ie.MoveNext();//执行到函数中遇到yield return为止
print(ie.Current);//得到return的值
MoveNext返回值代表是否达到了结尾(迭代器是否执行完毕)
while (ie.MoveNext())
{
print(ie.Current);
}
Unity的协程调度器:
继承MonoBehavior后 开启协程
相当于是把一个协程函数(迭代器)放入Unity的协程调度器中帮助我们管理进行执行
具体的yield return 后面的规则 也是unity定义的一些规则