一。什么是協同程序
協同程序,即在主程序運行時同時開啟另一段邏輯處理,來協同當前程序的執行。換句話說,開啟協同程序就是開啟一個線程。
二。協同程序的開啟與終止
在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;
}
}
}