• 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)

        {

        }




    你以为你在合群,其实你在浪费青春
  • 相关阅读:
    生成器,迭代器
    [LeetCode] Minimum Depth of Binary Tree
    [LeetCode] Sum Root to Leaf Numbers
    [LeetCode]Sort Colors
    [LeetCode] Remove Nth Node From End of List
    [LeetCode] Palindrome Number
    [LeetCode] Container With Most Water
    [LeetCode] Pascal's Triangle II
    [LeetCode] Path Sum
    [LeetCode] Search a 2D Matrix
  • 原文地址:https://www.cnblogs.com/soviby/p/10013297.html
Copyright © 2020-2023  润新知