一:什麼是協同程序。編程
協同程序,即主程序在運行的同時開啓另一段處理邏輯,相似於開啓一個線程。異步
注意:必須在MonoBehaviour函數
兩種開啓方法:性能
I:StartCoroutine(string methodName);this
最多隻能傳遞一個參數,比較消耗性能。spa
銷燬:開啓線程並在線程結束前終止線程(本身銷燬自己)線程
II:StartCoroutine(IEnumerator routinue);設計
只能等待線程的終止而不能隨時終止code
銷燬: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; } }
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."); } }
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.若是你想讓多個腳本訪問一個協程,能夠定義爲靜態的協程;
(這篇博客是參考網上某篇博客,本身簡化,加入了一點點本身的理解)