【Unity】协程

协程:在主程序运行的同时,开启另外一段逻辑处理,来协助主程序的执行。

协程的优点:能够分散主程序的计算压力,提高计算时长优化效率

协程的缺点:协程的本质是迭代器,是基于unity的生命周期的,大量的开启协程会引起GC,如果同时激活的协程较多,多个高开销的协程在同一帧执行导致卡顿。

协程函数:

IEnumerator Test()
{
    Debug.Log("开始");
    yield return new WaitForSeconds(5f);
    Debug.Log("已经开始了5s了");
}

IEnumerator Test(float timer)
{
    Debug.Log("开始");
    yield return new WaitForSeconds(timer);
    Debug.Log($"已经开始了{timer}了");
}

调用协程:

private void Start()
{
    //调用无参数的协程
    StartCoroutine(Test());
    StartCoroutine("Test");
    //调用有参数的协程
    StartCoroutine(Test(5.5f));
    StartCoroutine("Test",5.5f);     
}

终止协程:
 

//注意:当想停止某个协程时,开启与停止协程需要使用相同的形式,不可混合使用!

//记录协程并停止协程
Coroutine mCoroutine = null;
void Start()
{
    mCoroutine= StartCoroutine(Test());
}

void Stop()
{
    //如果开启协程时,用的是字符串(只能终止开启协程时以字符串为参数的协程)
    StopCoroutine("Test");

    //如果开启协程时,用的是函数名(只能终止开启协程时以函数名为参数的协程)
    StopCoroutine(Test());

    //以Coroutine为参数终止协程
    StopCoroutine(mCoroutine);
}

协程的优化:在协程中直接new一个中断指令,带来不必要的 GC 负担,可以使用一个全局的中断指令来优化

//全局中断指令
WaitForSeconds waitForSeconds = new WaitForSeconds(5f);
void Start()
{
    StartCoroutine(Test());
}
IEnumerator Test()
{
    Debug.Log("开始");
    yield return waitForSeconds;
    Debug.Log("已经开始了5s了");
}

协程中yield的用法:

//等待指定时间后执行(1S)
yield return new WaitForSeconds(1f);

//在FixedUpdate结束后再执行
yield return new WaitForFixedUpdate();

//在每帧结束后执行下面的
yield return new WaitForEndOfFrame();

//在指定协程执行后执行下面的
IEnumerator WaitTest()
{
//等待某个协程执行完毕后再执行后续代码
yield return StartCoroutine(Test());
Debug.Log("Good!");
}

//下一帧再执行下面的代码
IEnumerator WaitTest()
{
    //下一帧再执行下面的代码
    yield return null; 
    Debug.Log("Good!");
    //下一帧再执行下面的代码
    yield return 0;//这里可以填任意数字
    Debug.Log("haha!");
}

//直接结束协程的接下来的操作
yield break; 

对Unity协程的理解:协程不是线程,协程的实现原理是迭代器,迭代器的实现原理是状态机。
Unity中协程执行过程中,通过yield return......将程序挂起执行接下来的内容。在遇到yield return......语句之前,协程方法和一般的方法是相同的,也就是程序在执行到yield return......语句之后,接着才会执行的是StartCoroutine0方法之后的程序,走的还是单线程模式,仅仅是将yield return......语句之后的内容暂时挂起,等到特定的时间才执行。那么挂起的程序什么时候执行呢?协同程序主要是Update0方法之后,LateUpdate0方法之前调用的。通过设置MonoBehaviour脚本的enabled对协程是没有影响的,但如果是设置gameObject.SetActive(false)则已经启动的协程则完全停止了,即使在Inspector把gameObject激活还是没有继续执行。也就说协程虽然是在MonoBehaviour启动的(StartCoroutine) ,但是协程函数的地位完全是跟MonoBehaviour是一个层次的,不受MonoBehaviour的状态影响,但是跟MonoBehaviour脚本一样受gameObject控制,也应该是和MonoBehaviour脚本一样每帧轮询yield的条件是否满足。

Unity3D的协程和C#的线程之间的区别:多线程程序同时运行多个线程,而在任一指定时刻只有一个协程在运行,并且这个正在运行的协同程序只在必要时才被挂起。除主线程之外的线程无法访问Unity3D的对象、组件、方法。Unity3d没有多线程的概念,不过unity也给我们提供了StartCoroutine (协同程序)和LoadLevelAsync(异步加载关卡)后台加载场景的方法。StartCoroutine为什么叫协同程序呢, 所谓协同,就是当你在StartCoroutine的函数体里处理一段代码时, 利用yield语句等待执行结果,这期间不影响主程序的继续执行,可以协同工作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值