Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 257|回复: 0

[默认分类] IEnumerator 协程 全称协同程序

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-7-8 18:36:19 | 显示全部楼层 |阅读模式


      
       
      


      


      
       IEnumerator 协程 全称协同程序
      


      
       
       
       
          每次执行协程时,都会新建一个新(伪)线程去执行,第二次执行不会影响上一次的执行,
       
       
              结论是:协程适用于同一时间只运行一份函数的情况,如果同一时间运行多份同一个协程就会难以管理

       
       
         
             void Start()
         
         
              {
         
         
                 for (int i = 0; i < 7; i++)
         
         
                  {
         
         
                      StartCoroutine(SampleFunc(7)); //第二次执行时,会重新开启伪新线程执行,不会影响打断第一次执行,这里会开启7个伪线程,每个线程单独执行SampleFunc()函数
         
         
                  }
         
         
              }
         
         
             IEnumerator SampleFunc(inta)
         
         
              {
         
         
                 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)
           {
       
            }
       
      


      
       
       
       
      


      
      
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-23 21:12 , Processed in 0.339582 second(s), 35 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表