Unity3D--协程使用详解

1. 简介
unity的协程(Coroutine)是一个能够暂停协程执行,暂停后立即返回主函数,执行主函数剩余的部分,直到中断指令完成后,从中断指令的下一行继续执行协程剩余的函数。
函数体全部执行完成,协程结束,由于中断指令的出现,使得可以将一个函数分割到多个帧里去执行。

协程不是进程,也不是线程,它就是一个特殊的函数——可以在某个地方挂起,并且可以重新在挂起处继续运行。

协程方法与普通方法的区别:

普通方法
被调用时,原来执行的部分保留现场,停止执行,然后去执行要调用的方法,并且,被调用的方法执行完之后才能返回到调用前的状态接着往下执行。
协同方法
执行不用等协同方法执行完再执行调用之前原来方法的代码,而是两者异步执行。
协程不是多线程,它与主线程同时运行,它在主线程运行的同时开启另一段逻辑处理。
类似一个子线程单独出来处理一些问题,性能开销较小。
Unity的协程会在每帧结束之后去检测yield的条件是否满足,满足则执行yield return之后的代码。

在一个MonoBehaviour提供的主线程里只能有一个处于运行状态的协程,而其他协程处于休眠状态。
协程实际上是在一个线程中,只不过每个协程对CUP进行分时,协程可以访问和使用unity的所有方法和component。

性能:
在性能上相比于一般函数没有更多的开销

协程的好处:
让原来要使用异步 + 回调方式写的非人类代码, 可以用看似同步的方式写出来。
能够分步做一个比较耗时的事情,如果需要大量的计算,将计算放到一个随时间进行的协程来处理,能分散计算压力

协程的坏处:
协程本质是迭代器,且是基于unity生命周期的,大量开启协程会引起gc
如果同时激活的协程较多,就可能会出现多个高开销的协程挤在同一帧执行导致的卡帧


协程是在什么地方执行?
协程不是线程,不是异步执行;协程和monobehaviour的update函数一样也是在主线程中执行
unity在每一帧都会处理对象上的协程,也就是说,协程跟update一样都是unity每帧会去处理的函数。经过测试,协程至少是每帧的lateUpdate后运行的。
 

前驱知识:

  • 设计模式——迭代器模式
  • C#中的IEnumerator、IEnumerable接口

2. 协程的实现

协程的实现需要在Unity中继承MonoBehaviour并使用C#的迭代器IEnumrator,格式如下所示:

IEnumrator 函数名(形参表)  //最多只能有一个形参 
{   
    yield return xxx; //恢复执行条件
    //方法体
}

在IEnumerator类型的方法中写入需要执行的操作,遇到yield后会暂时挂起,等到yield return后的条件满足才继续执行yield语句后面的内容。

3. 协程的开启与中止

3.1 协程的开启
开启协程需要使用StartCoroutine()方法:

开启无参数的协程:
StartCoroutine(协程名());或StartCoroutine("协程名");

开启单参数的协程:
StartCoroutine(协程名(参数));或StartCoroutine("协程名",参数);

开启多参数的协程:
StartCoroutine(协程名(参数1,......));

 

void StartCoroutine()//开启协程的函数
{
    IEnumerator coroutine = Test(5, 6);
    StartCoroutine(coroutine);
}
 public IEnumerator Test(int a, int b)//协程
 {
     //等待帧画面渲染结束
     yield return new WaitForEndOfFrame();
     a=2;
     b=3;
}

用“协程名”启动的方式不允许传入 一个以上的参数。

3.2 协程的结束

结束协程有两种情况:

  • 当协程的方法体执行完毕将会自动结束

  • 调用StopCoroutine();方法中止协程执行

中止协程的几种情况:

  • 中止所有协程:
    StopAllCoroutines();

  • 使用对象实例中止指定协程

    Coroutine c;
    void Start()
    {
        c = StartCoroutine(CountSeconds());        
    }
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.J))
        {
            StopCoroutine(c);
        }
    }
    
  • 使用字符串中止指定协程

只有以协程名字符串启动的协程可以用此方法中止
既:StartCoroutine(“协程名”);StartCoroutine(“协程名”,参数);

允许使用**StopCoroutine(“协程名”);**中止协程

不允许使用直接调用协程方法的方式中止指定协程
既:**StopCoroutine(协程名([参数]));**不被允许

4. yield 协程回复条件语句

快查表:

yield语句 功能
yield return null; 下一帧再执行后续代码
yield return 0; 下一帧再执行后续代码
yield return 6;(任意数字) 下一帧再执行后续代码
yield break; 直接结束该协程的后续操作
yield return asyncOperation; 等异步操作结束后再执行后续代码
yield return StartCoroution(其它协程); 调用执行其它协程后再执行后续代码
yield return WWW(); 等待WWW操作完成后再执行后续代码
yield return new WaitForEndOfFrame(); 等待帧结束,等待直到所有的摄像机和GUI被渲染完成后,在该帧显示在屏幕之前执行
yield return new WaitForSeconds(0.3f); 等待0.3秒,一段指定的时间延迟之后继续执行,在所有的Update函数完成调用的那一帧之后(这里的时间会受到Time.timeScale的影响);
yield return new WaitForSecondsRealtime(0.3f); 等待0.3秒,一段指定的时间延迟之后继续执行,在所有的Update函数完成调用的那一帧之后(这里的时间不受到Time.timeScale的影响);
yield return WaitForFixedUpdate(); 等待下一次FixedUpdate开始时再执行后续代码
yield return new WaitUntil() 将协同执行直到当输入的参数(或者委托)为true的时候
yield return new WaitWhile() 将协同执行直到 当输入的参数(或者委托)为false的时候

生命周期图:

 转载:卖烤麸烤饼儿的博客_CSDN博客-一些尝试,Unity基础,C#领域博主卖烤麸烤饼儿擅长一些尝试,Unity基础,C#,等方面的知识,卖烤麸烤饼儿关注c#,unity,游戏程序,.net,游戏策划领域.https://blog.csdn.net/qq_44705559

猜你喜欢

转载自blog.csdn.net/weixin_45488182/article/details/125311242