Unity3D 協程 淺談


協程

一:什么是協同程序。

 協同程序,即主程序在運行的同時開啟另外一段處理邏輯,類似於開啟一個線程。

注意:必須在MonoBehaviour

兩種開啟方法:

 I:StartCoroutine(string methodName);

最多只能傳遞一個參數,比較消耗性能。

銷毀:開啟線程並在線程結束前終止線程(自己銷毀本身)

 

II:StartCoroutine(IEnumerator routinue);

只能等待線程的終止而不能隨時終止

銷毀:StopAllStoroutines(),  

協同程序所在的gameObject 的 active屬性設置為false,再次設置active為true,協同程序將不會再次開啟。

如果將協同程序所在的腳本的enable設置為false則不會消失。這是因為協同程序被開啟后作為一個線程在運行,

而MonoBehaviour也是一個線程,他們成為互不干擾的的模塊。他們公用一個對象,只有在這個對象不可見才能同時終止這兩個線程。然而為了

管理我們額外開啟的線程,Unity3D將協同程序的調用放在了MonoBehaviour中,這樣在編程時就可以方便的調用指定的腳本中的協同程序,而不是

無法去管理,特別是對於只根據方法名來判斷線程的方式在多人開發中很容易出錯,這樣的設計是為了保證對象,腳本的條件管理,並防止重名。

 

yield :代表先執行完本局語句(不管時間多長),或者執行完本yield方法調用,才執行后面的語句。

看下面的例子,數字代表着執行的順序

 private void Awake()
    {
        Debug.Log("11");
        StartCoroutine(DoTest());
        Debug.Log("333");
    }
    // Use this for initialization
    void Start()
    {
        Debug.Log("444");
    }

    IEnumerator DoTest()
    {
        Debug.Log("222");
        yield return new WaitForSeconds(1.0f);
        Debug.Log("555");
    }

  

void Awake()
    {
        Debug.Log("00");
        StartCoroutine(StartTest());
        Debug.Log("2");
    }
    IEnumerator StartTest()
    {
        yield return StartCoroutine("Do");
        Debug.Log("4");
    }

    IEnumerator Do()
    {
        Debug.Log("1 Now");
        yield return null;
        Debug.Log("3");
    }

 

 

 

理解:協程不是線程,也不是異步執行(知道就行)。

1.協程和MonoBehaviour的Update函數一樣,也是在MainThread中執行的(一定得明白這句話意思)。

	void Start () {
        StartCoroutine(HelloCoroutine());
	}
	
	void Update () {
        Debug.Log("Update...");
    }
    void LateUpdate()
    {
        Debug.Log("LateUpdate...");
    }
    IEnumerator HelloCoroutine()
    {
        while (true)
        {
            Debug.Log("Coroutine...");
            yield return null;
        }
    }


 
        
 
對比以上代碼和兩張截圖。這樣寫協程,好像是高級一點的Update寫法。至少應該可以看出,這種寫法的協程可以完成update的功能。

2.與update不一樣的地方。
 IEnumerator Count()
    {
        int seconds = 0;
        while (true)
        {
            for (float timer = 0; timer < 2; timer += Time.deltaTime)
                yield return 0;

            seconds++;
            Debug.Log(seconds + " seconds have passed since the Coroutine started.");
        }
    }

  

3.yield

  yiled return null  等同於 yield return 0

我這邊的理解是,停止正在執行的方法,並從下一幀開始執行(一般是0.02秒,與Update的每一幀是一樣的,具體看Unity設置的timer)。

 

4.協程是可以傳遞參數的。

5.協程還可以嵌套協程。

IEnumerator HelloCoroutinue()
    {
        Debug.Log("Start----");
        yield return StartCoroutine(Wait(0.2f)); //  yield return new WaitForSeconds(0.2f);最終達到的效果是一樣的。
        Debug.Log("End----");
}
    IEnumerator Wait(float s)
    {
        for(float timer =0;timer< s;timer+=Time.deltaTime)
        {
            Debug.Log("當前 timer" + timer.ToString());
            yield return 0; // yield return null;
        }
        Debug.Log("Wait.....");
    }

  

看截圖中畫線的時間差,再次驗證了與Update好像。暫停的時間都是一樣的。

可以看到暫停了當前的方法去執行yield return后的方法。

 

補充注意: 

           a.多個協程可以同時運行,它們會根據各自的啟動順序來更新;

    b.如果你想讓多個腳本訪問一個協程,可以定義為靜態的協程;

 

  (這篇博客是參考網上某篇博客,自己簡化,加入了一點點自己的理解)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM