一。什麼是協同程式
協同程式,即在主程式運行時同時開啟另一段邏輯處理,來協同當前程式的執行。換句話說,開啟協同程式就是開啟一個線程。
二。協同程式的開啟與終止
在Unity3D中,使用MonoBehaviour.StartCoroutine方法即可開啟一個協同程式,也就是說該方法必須在MonoBehaviour或繼承於MonoBehaviour的類中調用。
在Unity3D中,使用StartCoroutine(string methodName)和StartCoroutine(IEnumerator routine)都可以開啟一個線程。區別在於使用字串作為參數可以開啟線程並線上程結束前終止線程,相反使用IEnumerator 作為參數只能等待線程的結束而不能隨時終止(除非使用StopAllCoroutines()方法);另外使用字串作為參數時,開啟線程時最多隻能傳遞一個參數,並且效能消耗會更大一點,而使用IEnumerator
作為參數則沒有這個限制。
在Unity3D中,使用StopCoroutine(string methodName)來終止一個協同程式,使用StopAllCoroutines()來終止所有可以終止的協同程式,但這兩個方法都只能終止該MonoBehaviour中的協同程式。
還有一種方法可以終止協同程式,即將協同程式所在gameobject的active屬性設定為false,當再次設定active為ture時,協同程式並不會再開啟;如是將協同程式所在指令碼的enabled設定為false則不會生效。這是因為協同程式被開啟後作為一個線程在運行,而MonoBehaviour也是一個線程,他們成為互不干擾的模組,除非代碼中用調用,他們共同作用於同一個對象,只有當對象不可見才能同時終止這兩個線程。然而,為了管理我們額外開啟的線程,Unity3D將協同程式的調用放在了MonoBehaviour中,這樣我們在編程時就可以方便的調用指定指令碼中的協同程式,而不是無法去管理,特別是對於只根據方法名來判斷線程的方式在多人開發中很容易出錯,這樣的設計保證了對象、指令碼的條理化管理,並防止了重名。
三。協同程式的輸入、輸出類型
協同程式的傳回型別為Coroutine類型。在Unity3D中,Coroutine類繼承於YieldInstruction,所以,協同程式的傳回型別只能為null、等待的幀數(frame)以及等待的時間。
協同程式的參數不能指定ref、out參數。但是,我們在使用WWW類時會經常使用到協同程式,由於在協同程式中不能傳遞參數地址(引用),也不能輸出對象,這使得每下載一個WWW對象都得重寫一個協同程式,解決這個問題的方法是建立一個基於WWW的類,並實現一個下載方法。如下:
usingUnityEngine;
usingSystem.Collections;
publicclassWWWObject:MonoBehaviour
{
public WWW www;
publicWWWObject(string url)
{
if(GameVar.wwwCache)
www =WWW.LoadFromCacheOrDownload(url,GameVar.version);
else
www =new WWW(url);
}
publicIEnumeratorLoad()
{
Debug.Log("Start loading : "+www.url);
while(!www.isDone)
{
if(GameVar.gameState
==GameState.Jumping||GameVar.gameState
==GameState.JumpingAsync)
LoadScene.progress
=www.progress;
yieldreturn1;
}
if(www.error!=null)
Debug.LogError("Loading error : "+www.url+"\n"+www.error);
else
Debug.Log("End loading : "+www.url);
}
publicIEnumeratorLoadWithTip(string resourcesName)
{
Debug.Log("Start loading : "+www.url);
LoadScene.tipStr
= "Downloading resources <"+ resourcesName
+"> . . .";
while(!www.isDone)
{
if(GameVar.gameState
==GameState.Jumping||GameVar.gameState
==GameState.JumpingAsync)
LoadScene.progress
=www.progress;
yieldreturn1;
}
if(www.error!=null)
Debug.LogError("Loading error : "+www.url+"\n"+www.error);
else
Debug.Log("End loading : "+www.url);
}
}
調用:
usingUnityEngine;
usingSystem.Collections;
usingSystem.Collections.Generic;
publicclassLoadResources:MonoBehaviour
{
staticstring url
="http://61.149.211.88/Package/test.unity3d";
publicstatic WWW www
=null;
IEnumeratorStart()
{
if(!GameVar.resourcesLoaded)
{
GameVar.gameState
=GameState.Jumping;
WWWObject obj
=newWWWObject(url);
www = obj.www;
yieldreturnStartCoroutine(obj.LoadWithTip("Textures"));
GameVar.resourcesLoaded
=true;
GameVar.gameState
=GameState.Run;
}
}
}