zoukankan      html  css  js  c++  java
  • IEnumerator 协程 全称协同程序

    IEnumerator 协程 全称协同程序

     每次 执行协程 时,都会新建一个新()线程去执行,第二次执行不会影响上一次的执行,
         结论是:协程适用于同一时间只运行一份函数的情况,如果同一时间运行多份同一个协程就会难以管理
        void Start()
        {
            for (int i = 0; i < 7; i++)
            {
                StartCoroutine(SampleFunc(7));  //第二次执行时,会重新开启伪新线程执行,不会影响打断第一次执行,这里会开启7个伪线程,每个线程单独执行SampleFunc()函数
            }
        }
        IEnumerator SampleFunc(int a)
        {
            while (a != 0)
            {
                a--;
                Debug.Log("a=============== "+ a);   //输出了 7*7=49 句 a 的值
                yield return new WaitForSeconds(0.1f);
            }
        }
     
    表达式
    yield return null;  //等1帧执行.暂停协同程序,下一帧再继续往下执行. 通知协程管理器,我到这个点要中断一下,下一帧从这个地方运行而已.
    yield return 0;      //同yield return null;,数字改多大没用,都是等一帧
    yield return 666; //同yield return null;,数字改多大没用,都是等一帧
    yield break; //不在执行下面的语句,直接rerun
    yield return asynaOperation; //等待异步操作执行完毕后执行
    yield return StartCoroutine(coroutine); //等待子协程执行完毕后再执行
    yield return  WWW();    在WWW下载完成之后……waits for a web request to complete (resumes as if WaitForSeconds or null)
    yield return new WaitForEndOfFrame(); //等待帧结束,等待直到所有的摄像机和GUI被渲染完成后,在该帧显示在屏幕之前。用在while循环里减少死机
    yield return new WaitForSeconds(0.3f);//等待0.3秒 , 一段指定的时间延迟之后继续执行,在所有的Update函数完成调用的那一帧之后注意:受Time.timeScale影响,当Time.timeScale = 0f 时,yield return new WaitForSecond(x) 将不会满足。
    yield return new WaitForFixedUpdate(); // 所有脚本上的FixedUpdate函数已经执行调用之后持续
    yield return new WaitUntil:将协同执行直到 当输入的参数(或者委托)为true的时候……  || yield return new WaitUntil(() => frame >= 10);
    yield return new  WaitWhile:将协同执行直到 当输入的参数(或者委托)为false的时候…… || yield return new WaitWhile(() => frame < 10);

    协程其实就是一个IEnumerator(迭代器),IEnumerator 接口有两个方法 Current 和 MoveNext() ,只有当MoveNext()返回 true时才可以访问 Current,否则会报错。迭代器方法运行到 yield return 语句时,会返回一个expression表达式并保留当前在代码中的位置。 当下次调用迭代器函数时执行从该位置重新启动。

    Unity在每帧做的工作就是:调用 协程(迭代器)MoveNext() 方法,如果返回 true ,就从当前位置继续往下执行。


    yield return 被会“翻译”为一个 IEnmerator 对象,这个对象实现的 MoveNext() 包含函数内所有 yield return 的处理

    函数内有多少个 yield return 在对应的 MoveNext() 就会返回多少次 true (不包含嵌套)。

    另外非常重要的一点的是:同一个函数内的其他代码(不是 yield return 语句)会被移到 MoveNext 中去,也就是说,每次 MoveNext 都会顺带执行同一个函数中 yield return 之前,之后 和两个 yield return 之间的代码。



    协程不是线程,也不是异步执行的,是Unity每帧LateUpdate()之后都会去处理的函数


    协程执行流程

    1 如果 [gameObject激活] 并且 [脚本.enable=true ] 状态 下, StartCoroutine启动了协程 ,协程会立即运行到第一个 yield return 语句处,控制权交给外部

    2. 等待Unity在下一帧(Frame)LateUpdate()之后

    3.检查协程是否允许的条件 : 

    脚本.enabled = false 协程会照常运行

    a.检测 gameObject 是否处于激活(active) ,不激活不运行

    b.检测 yield return 后面的表达式,如果满足就继续向下执行


    IEnumerator 协程  全称协同程序

    1.必须在MonoBehaviour或继承于MonoBehaviour的类中调用 yield coroutine。

    2.StartCoroutine所在脚本物体必须是激活的.才能执行不报错.


    MonoBehaviour.StartCoroutine方法即可开启一个协同程序,


    StopCoroutine(methodName())//来终止一个协同程序,

    StopAllCoroutines()//来终止所有可以终止的协同程序,

    但这两个方法都只能终止该MonoBehaviour中的协同程序。

    MonoBehaviour.enabled = false 协程会照常运行,gameObject.SetActive(false) 停止,即使在Inspector把  gameObject 激活还是没有继续执行



    //yield return 被会“翻译”为一个 IEnmerator 对象

    //yiled return 本质上和return作用一样,将当前函数返回。只不过下一次再调用这个函数,可以从yiled return的下一句开始执行,函数本身的变量也都会一直保存上一次调用的状态。

    //yield return的作用是在执行到这行代码之后,将控制权立即交还给外部。yield return之后的代码会在外部代码再次调用MoveNext时才会执行,直到下一个yield return——或是迭代结束

    yield return expression; //只有表达式完全执行结束才会继续执行后面的代码


    结束返回:

    在迭代器块中用于向枚举数对象提供值或发出迭代结束信号。它的形式为下列之一⑥:

      yield return <expression_r>;

      yield break;


    //==========================列0=============================

        void Start()

        {

            StartCoroutine(WaitEnd (5f)); // 瞬间执行 WaitEnd函数 ,和下面的函数

            StartCoroutine (WaitFrameEnd());// 瞬间执行 WaitFrameEnd函数 ,和下面的函数        

    StartCoroutine (WaitFixedUpdate());// 瞬间执行 WaitFixedUpdate函数 ,和下面的函数    

        }

     

        IEnumerator WaitEnd(float time)

        {    // 执行同时,其他函数也再并行

            yield return new WaitForSeconds(time);

                // 5秒后到这里 ,执行这里的

            Debug.Log ("WaitForSeconds:"+time);

        }

     

        IEnumerator WaitFrameEnd()

        {    

            yield return new WaitForEndOfFrame();

             // 等待当前帧结束 

            Debug.Log ("WaitForEndOfFrame:"+Time.time);

        }

     

        IEnumerator WaitFixedUpdate()

        {

            yield return new WaitForFixedUpdate();

                // 等待每次 Update 执行一次后调用

            Debug.Log ("WaitForFixedUpdate:"+Time.time);

        }


    //==========================列1=============================

    IEnumerator WaitAndshen()

    {

    yield return new WaitForSeconds(0.3f);

    //上面的时间到了才能执行下面的.

    }

    //注意 StartCoroutine 所在脚本物体必须是激活的.才能执行不报错.

    StartCoroutine( WaitAndshen());

    //==========================列2 带参数的协程=============================

     void Start()

     {

    StartCoroutine(_PlayLoopSound(clip, delay, time, fadeInTime, fadeOutTime));

     }


        IEnumerator _PlayLoopSound(AudioClip clip, float delay, float time, float fadeInTime, float fadeOutTime)

        {

        }




    你以为你在合群,其实你在浪费青春
  • 相关阅读:
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    使用Jasmine和karma对传统js进行单元测试
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    nginx 基于IP的多虚拟主机配置
    Shiro 框架的MD5加密算法实现原理
    项目实战:Qt+OSG三维点云引擎(支持原点,缩放,单独轴或者组合多轴拽拖旋转,支持导入点云文件)
    实用技巧:阿里云服务器建立公网物联网服务器(解决阿里云服务器端口,公网连接不上的问题)
  • 原文地址:https://www.cnblogs.com/soviby/p/10013297.html
Copyright © 2011-2022 走看看