• Unity3D 协程的介绍和使用


    我是快乐的搬运工 http://blog.csdn.net/u011397120/article/details/61236055

    ---------------------------------------------------------------------- 分割线 xx --------------------------------------------------------------------------

    本文是个人对Unity协程的一些理解和总结.Unity协程长的有点像线程,但却不是线程.因为协程仍然是在主线程中执行,且在使用时不用考虑同步与锁的问题.协程只是控制代码等到特定的时机后再执行后续步骤.

    启动协程

    Unity 5.x中使用StartCoroutine方法开启协程,其方式有以下几种.

    //形式一 
    StartCoroutine(CustomCorutineFn()); 
     StartCoroutine(CustomCorutineFn(7));//向方法中传递参数 
    //形式二 
    StartCoroutine(“CustomCorutineFn”); 
    StartCoroutine(“CustomCorutineFn”,7);//向方法中传递参数
    

    以上两种形式都可开起当前MonoBehaviour对象的协程,注意:当你想停止MonoBehaviour对象中的某个协程时,开启与停止协程需要使用相同的形式,不可混合使用.
    协程中有多种等待方式,例如:等到FixedUpdate结束后才执行,代码如下.

        bool canExcute = true;
        void FixedUpdate()
        {
            if (canExcute)
            {
                Debug.Log("FixedUpdate" );
            }
        }
        IEnumerator Corutine_WaitForFixedUpdate()
        {
            yield return new WaitForFixedUpdate();
            Debug.Log(string .Format("====>{0}    time:{1}", 1, Time .time));
            yield return new WaitForFixedUpdate();
            Debug.Log(string .Format("====>{0}    time:{1}", 2, Time .time));
        }
    

    输出结果如下.

    官方文档Monobehaviour的函数执行顺序图,就对协程再次执行的时机做了很好的描述.

    以上只是一个示意图,详细信息请看官方文档.
    链接 https://docs.unity3d.com/Manual/ExecutionOrder.html

    yield null:协程将在下一帧所有脚本的Update执行之后,再继续执行. 
    yield WaitForSeconds:协程在延迟指定时间,且当前帧所有脚本的 Update全都执行结束后才继续执行. 
    yield WaitForFixedUpdate:协程在所有脚本的FixedUpdate执行之后,再继续执行. 
    yield WWW:协程在WWW下载资源完成后,再继续执行. 
    yield StartCoroutine:协程在指定协程执行结束后,再继续执行. 
    WaitForSecondsRealtime:与WaitForSeconds类似,但不受时间缩放影响. 
    WaitWhile:当返回条件为假时才执行后续步骤.
    

    协程的执行也会受到其他因素的影响,例如:当时间缩放值Time.timeScale被修改后,放大或者缩小.FixedUpdate 方法会受影响,则WaitForFixedUpdate也会跟着受影响;当Update方法中同步加载较大的对象时,WaitForSeconds所指定的时间就可能会与实际的时间不一致.所以在执行协程等待时,要视情况而定.

    多个gameObject对象开启协程,执行顺序又是如何呢?
    假如场景中存在A,B两个gameObject对象,均使用WaitForFixedUpdate方式等待,则等待执行的部分,会在A,B两个对象的FixedUpdate都执行结束后,才开始执行当前帧后续可执行的部分.源码如下:

        void Awake()
        {
            StartCoroutine(Corutine_WaitForFixedUpdate());
        }
        IEnumerator Corutine_WaitForFixedUpdate()
        {
            Debug.Log(string .Format("A : {0}", 0));
            yield return new WaitForFixedUpdate();
            Debug.Log(string .Format("A : {0}", 1));
        }
        bool canExcute = false;
        void FixedUpdate()
        {
            if (!canExcute)
            {
                canExcute = true;
                Debug.Log("A FixedUpdate" );
            }
        }
    

     执行后输出结果如下.

    停止协程

    在开发中可能会开启多个协程,如果你想停止其中某个协程,你可使用StopCoroutine.但在使用时,你需要注意一点,停止协程的方式要与开启协程的方式一致.StopCoroutine(“CustomCorutineFn”)必须与StartCoroutine(“CustomCorutineFn”)成对使用,与StartCoroutine(CustomCorutineFn())一起使用则完全无效.
    通过StopCoroutine的重载方法可知道,还有两种方式可停止协程.在此举个例子,如下:

        IEnumerator cor;
        void Awake()
        {
            //注意保存IEnumerator变量.
            cor = Corutine_WaitForFixedUpdate();
            StartCoroutine(cor);
            StartCoroutine(Corutine_Stop());
        }
        IEnumerator Corutine_WaitForFixedUpdate()
        {
            Debug.Log(string .Format("A : {0}", 0));
            yield return new WaitForEndOfFrame();
            Debug.Log(string .Format("A : {0}", 1));
        }
        IEnumerator Corutine_Stop()
        {
            yield return new WaitForFixedUpdate();
            //通过cor停止协程
            //而不是this.StopCoroutine(Corutine_WaitForFixedUpdate());
            this.StopCoroutine(cor);
        }
    

    如果想停止多个协程,可使用StopAllCoroutines方法,但这种方法只能停止当前MonoBehaviour类实例中所有协程.其他不受影响.
    如果想停止gameObject上所有脚本组件中的协程,禁用脚本组件是无法停止协程的,只需要禁用gameObject即可.

    如何用协程的输出10组计数(每组5次,每次1秒)?
    源码如下:

    using System.Collections;
    using UnityEngine;
    
    public class mCorutine : MonoBehaviour
    {
        public float time = 1;
        void Awake()
        {
            StartCoroutine(FirstLayerCorutine());
        }
        IEnumerator FirstLayerCorutine()
        {
            for (int i = 0; i < 10; i++)
            {
                Debug.Log(string .Format("第{0}组", i + 1));
                yield return StartCoroutine(SecondLayerCorutine());
            }
        }
        IEnumerator SecondLayerCorutine()
        {
            for (int i = 0; i < 5; i++)
            {
                Debug.Log(string .Format("{0}", i + 1));
                yield return new WaitForSeconds(time);
            }
        }
    }
    

    协程的使用还有很多要注意的地方,在这里分享一个关于协程运行时的监控和优化的链接.
    http://gulu-dev.com/post/perf_assist/2016-12-20-unity-coroutine-optimizing

  • 相关阅读:
    Windows SDK编程(Delphi版) 之 应用基础,楔子
    一个小问题引发的论证思考
    Delphi 组件开发教程指南(7)继续模拟动画显示控件
    用PyInstaller将python转成可执行文件exe笔记
    使用 .Net Memory Profiler 诊断 .NET 应用内存泄漏(方法与实践)
    Microsof Office SharePoint 2007 工作流开发环境搭建
    How to monitor Web server performance by using counter logs in System Monitor in IIS
    LINQ之Order By
    window 性能监视器
    内存泄露检测工具
  • 原文地址:https://www.cnblogs.com/crazytomato/p/8178382.html
Copyright © 2020-2023  润新知