Unity3D 協程的介紹和使用

我是快樂的搬運工 http://blog.csdn.net/u011397120/article/details/61236055html

---------------------------------------------------------------------- 分割線 xx --------------------------------------------------------------------------函數

本文是我的對Unity協程的一些理解和總結.Unity協程長的有點像線程,但卻不是線程.由於協程仍然是在主線程中執行,且在使用時不用考慮同步與鎖的問題.協程只是控制代碼等到特定的時機後再執行後續步驟.post

啓動協程優化

Unity 5.x中使用StartCoroutine方法開啓協程,其方式有如下幾種.this

//形式一 
StartCoroutine(CustomCorutineFn()); 
 StartCoroutine(CustomCorutineFn(7));//向方法中傳遞參數 
//形式二 
StartCoroutine(「CustomCorutineFn」); 
StartCoroutine(「CustomCorutineFn」,7);//向方法中傳遞參數

以上兩種形式均可開起當前MonoBehaviour對象的協程,注意:當你想中止MonoBehaviour對象中的某個協程時,開啓與中止協程須要使用相同的形式,不可混合使用.
協程中有多種等待方式,例如:等到FixedUpdate結束後才執行,代碼以下.spa

    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));
    }

輸出結果以下..net

官方文檔Monobehaviour的函數執行順序圖,就對協程再次執行的時機作了很好的描述.線程

以上只是一個示意圖,詳細信息請看官方文檔.
連接 https://docs.unity3d.com/Manual/ExecutionOrder.html3d

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都執行結束後,纔開始執行當前幀後續可執行的部分.源碼以下:orm

    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

相關文章
相關標籤/搜索