Coroutine:協(xié)同程序(簡(jiǎn)稱:協(xié)程),參考網(wǎng)絡(luò)給出以下兩個(gè)定義供參考。
成都創(chuàng)新互聯(lián)公司主要從事成都網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)頁設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)湖濱,10余年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):028-86922220
1> 協(xié)同程序,即在主程序運(yùn)行時(shí)同時(shí)開啟另一段邏輯處理,來協(xié)同當(dāng)前程序的執(zhí)行。換句話說,開啟協(xié)同程序就是開啟一個(gè)模擬線程。 [作者注: 不是真正的線程]
2>是一種很古老的編程模型,以前的操作系統(tǒng)里進(jìn)程調(diào)度里用到過,現(xiàn)在操作系統(tǒng)的進(jìn)程調(diào)度都是根據(jù)時(shí)間片和優(yōu)先級(jí)來進(jìn)行輪換,以前是要程序自己來釋放cpu的控制權(quán),一直不釋放一直也就占用著cpu,這種要求程序自己來進(jìn)行調(diào)度的編程模型應(yīng)該就叫“協(xié)程”。
語法:
function StartCoroutine (routine:IEnumerator) : Coroutine
function StartCoroutine (methodName:string, value : object = null) : Coroutine
function StopCoroutine (methodName:string) : void
function StopAllCoroutines () : void
示例:
void Start()
{
print("1: " + Time.time);
StartCoroutine(WaitAndPrint(2.0F));
print("3: " + Time.time);
}
IEnumerator WaitAndPrint(float waitTime)
{
yield return newWaitForSeconds(waitTime);
print("2: " +Time.time.ToString());
}
輸出結(jié)果:
1: 0
3: 0
2: 2.004061
Invoke:調(diào)用函數(shù),指每隔多少時(shí)間執(zhí)行一次某方法。
InvokeRepeating:重復(fù)調(diào)用函數(shù),指在給定時(shí)間后指定間隔時(shí)間后重復(fù)執(zhí)行方法。
語法:
function Invoke (methodName: string, time :float) : void
functionInvokeRepeating (methodName :String,time : float, repeatRate : float) : void
function CancelInvoke () : void
function IsInvoking (methodName: string) :bool
示例:
private int _IntNumber = 0; //累加數(shù)字
void Start()
{
//this.Invoke("DisplayNum",1F); //只調(diào)用一次
this.InvokeRepeating("DisplayNum", 0F, 1F); //間隔1秒反復(fù)調(diào)用
}
//每隔一定時(shí)間,進(jìn)行自增想加數(shù)字且輸出結(jié)果
void DisplayNum()
{
Debug.Log("自增數(shù)字: " + (++_IntNumber));
}
輸出結(jié)果:
自增數(shù)字:1
自增數(shù)字:2
自增數(shù)字:3
自增數(shù)字:4
自增數(shù)字:5
自增數(shù)字:6
(結(jié)果會(huì)無限循環(huán)下去...)
以上技術(shù)在Unity 實(shí)際編程過程中被大量應(yīng)用,個(gè)人體會(huì)Invoke 與 InvokeRepeating 為 Coroutine 的簡(jiǎn)化寫法,是按照事先定義好的固定時(shí)間間隔進(jìn)行調(diào)用的編程模型。優(yōu)點(diǎn)是結(jié)構(gòu)與語法編寫簡(jiǎn)單。Coroutine 則是更加完善,功能更加強(qiáng)大的編程模型。在處理需要制作多種間隔時(shí)間,從而達(dá)到一定功能的地方有良好的應(yīng)用效果。以下是開發(fā)與教學(xué)過程中實(shí)際的應(yīng)用場(chǎng)景舉例:
開發(fā)游戲倒計(jì)時(shí)案例。
(示例 1.1)
using UnityEngine;
using System.Collections;
public class GUIProgress_LevelOne : MonoBehaviour {
publicGUISkin projectWukongSkin; //項(xiàng)目皮膚
publicTexture2D TexGameOver_Falure; //游戲結(jié)束貼圖。
publicTexture2D TexNumberOne; //數(shù)字貼圖1
publicTexture2D TexNumberTwo;
publicTexture2D TexNumberThree;
//項(xiàng)目信息貼圖
publicTexture2D TexProjectLogo; //項(xiàng)目Logo
publicTexture2D TexRedDiamond; //紅寶石
privatebool _BoolIsDrawCountDownFlag = false; //繪制倒計(jì)時(shí)數(shù)字
private int_IntDrawNumber = 3; //繪制具體數(shù)字
void Start()
{
//啟動(dòng)游戲倒計(jì)時(shí)
StartCoroutine(DrawGameStartCountDown());
}//Start_end
//游戲開始倒計(jì)時(shí)
IEnumeratorDrawGameStartCountDown()
{
//1秒的準(zhǔn)備
yieldreturn new WaitForSeconds(1F);
//顯示數(shù)字3
_BoolIsDrawCountDownFlag = true;
_IntDrawNumber = 3;
yieldreturn new WaitForSeconds(1F); //停留1秒的查看時(shí)間
//空白時(shí)間
_BoolIsDrawCountDownFlag = false;
yieldreturn new WaitForSeconds(0.5F);
//顯示數(shù)字2
_BoolIsDrawCountDownFlag = true;
_IntDrawNumber = 2;
yieldreturn new WaitForSeconds(1F);
//空白時(shí)間
_BoolIsDrawCountDownFlag = false;
yieldreturn new WaitForSeconds(0.5F);
//顯示數(shù)字1
_BoolIsDrawCountDownFlag = true;
_IntDrawNumber = 1;
yieldreturn new WaitForSeconds(1F);
_BoolIsDrawCountDownFlag = false;
//開始游戲。
GlobalInfoManger.CurrentGameState = GameState.Playing;
}
void OnGUI()
{
GUI.skin = projectWukongSkin;
/*顯示項(xiàng)目信息 */
//項(xiàng)目Logo
GUI.DrawTexture(new Rect(Screen.width / 2 - TexProjectLogo.width/2, 0,TexProjectLogo.width, TexProjectLogo.height), TexProjectLogo);
//紅寶石
GUI.DrawTexture(new Rect(0, 0,50,50), TexRedDiamond);
//紅寶石當(dāng)前的數(shù)量
GUI.Label(newRect(50,0,100,100),GlobalInfoManger.IntRedDiamonds.ToString());
//顯示游戲時(shí)間
GUI.Label(new Rect(170, 0,150,80),"Time:");
//當(dāng)前游戲的時(shí)間
GUI.Label(new Rect(300, 0, 100, 100),GlobalInfoManger.IntGameTime.ToString());
//繪制游戲不成功貼圖畫面
if(GlobalInfoManger.CurrentGameState==GameState.GameOver)
{
GUI.DrawTexture(new Rect(Screen.width / 2 - TexGameOver_Falure.width /2, Screen.height / 2 - TexGameOver_Falure.height / 2, TexGameOver_Falure.width,TexGameOver_Falure.height), TexGameOver_Falure);
}
#region繪制倒計(jì)時(shí)數(shù)字貼圖
//繪制倒計(jì)時(shí)數(shù)字貼圖
if(_BoolIsDrawCountDownFlag)
{
if(_IntDrawNumber == 3)
{
GUI.DrawTexture(new Rect(Screen.width / 2 - TexNumberThree.width / 2,Screen.height / 2 - TexNumberThree.height / 2, TexNumberThree.width,TexNumberThree.height), TexNumberThree);
}
else if (_IntDrawNumber == 2)
{
GUI.DrawTexture(new Rect(Screen.width / 2 - TexNumberTwo.width / 2,Screen.height / 2 - TexNumberTwo.height / 2, TexNumberTwo.width,TexNumberTwo.height), TexNumberTwo);
}
else if (_IntDrawNumber == 1)
{
GUI.DrawTexture(new Rect(Screen.width / 2 - TexNumberOne.width / 2,Screen.height / 2 - TexNumberOne.height / 2, TexNumberOne.width,TexNumberOne.height), TexNumberOne);
}
}
#endregion
}//OnGUI_end
}//Class_end
圖 1.1
示例 1.1 參考圖1.1進(jìn)行理解,基本原理如下:
以上定義的協(xié)程方法 “DrawGameStartCountDown()” 主要是運(yùn)用 “_BoolIsDrawCountDownFlag”與“_IntDrawNumber ” 這兩個(gè)字段對(duì) OnGUI() 事件函數(shù)中“GUI.DrawTexture ” 繪制貼圖的時(shí)間間隔與繪制內(nèi)容進(jìn)行控制。
再舉一例:
開發(fā)游戲戰(zhàn)績(jī)數(shù)值統(tǒng)計(jì)案例。
(示例 1.2)
usingUnityEngine;
usingSystem.Collections;
public classGUI_CountResult : MonoBehaviour {
public GUISkin ProjectGUISkin; //項(xiàng)目皮膚
public Texture2D TexGameBackground; //游戲背景貼圖
public Texture2D TexRedDiamonds; //紅寶石貼圖
public Texture2D TexBlueDiamonds; //藍(lán)寶石貼圖
public string StrScenesName; //場(chǎng)景名稱。
public Texture2D TexRePlay; //"重玩"貼圖
private bool _boolRePlay = false; //是否重玩
private bool _boolExit = false; //是否退出
//開發(fā)動(dòng)態(tài)文字顯示
private int _IntRunedTime = 0; //玩家跑過的時(shí)間。
private bool _BoolIsDisplayRunedTime =false; //是否顯示跑過的里程
private int _IntRedDiamondNum = 0; //玩家跑過的時(shí)間。
private bool _BoolIsDisplayRedDiamond =false; //是否顯示跑過的里程
void Start ()
{
//測(cè)試數(shù)值(等待刪除。)
//GlobalInfoManger.IntGameTime = 66;
//GlobalInfoManger.IntRedDiamonds = 88;
//開啟“動(dòng)態(tài)控制顯示玩家跑過的里程(時(shí)間)”
StartCoroutine(DynamicDisplayPlayerRunLength());
//開啟“動(dòng)態(tài)控制紅寶石數(shù)量統(tǒng)計(jì)”
StartCoroutine(DynamicDisplayRedDiamondNumber());
}//Start_end
//動(dòng)態(tài)控制里程顯示
IEnumerator DynamicDisplayPlayerRunLength()
{
//等待GUI 與攝像機(jī)全部繪制完畢。
yield return new WaitForEndOfFrame();
_BoolIsDisplayRunedTime = true;
_IntRunedTime = 0;
yield return new WaitForSeconds(0.2F);
_BoolIsDisplayRunedTime = false;
while (_IntRunedTime <GlobalInfoManger.IntGameTime)
{
//不斷顯示
++_IntRunedTime;
_BoolIsDisplayRunedTime = true;
yield return newWaitForSeconds(0.03F);
_BoolIsDisplayRunedTime = false;
yield return new WaitForSeconds(0.01F);
}
_BoolIsDisplayRunedTime = true;
}
//動(dòng)態(tài)控制紅寶石顯示
IEnumeratorDynamicDisplayRedDiamondNumber()
{
//等待GUI 與攝像機(jī)全部繪制完畢。
yield return new WaitForEndOfFrame();
_BoolIsDisplayRedDiamond = true;
_IntRedDiamondNum = 0;
yield return new WaitForSeconds(0.2F);
_BoolIsDisplayRedDiamond = false;
while (_IntRedDiamondNum <GlobalInfoManger.IntRedDiamonds)
{
//不斷顯示
++_IntRedDiamondNum;
_BoolIsDisplayRedDiamond = true;
yield return newWaitForSeconds(0.03F);
_BoolIsDisplayRedDiamond = false;
yield return newWaitForSeconds(0.01F);
}
_BoolIsDisplayRedDiamond = true;
}
void OnGUI()
{
GUI.skin=ProjectGUISkin;
//繪制游戲背景貼圖
GUI.DrawTexture(newRect(Screen.width/2-TexGameBackground.width/2,Screen.height/2-TexGameBackground.height/2,TexGameBackground.width,TexGameBackground.height),TexGameBackground);
//顯示統(tǒng)計(jì)玩家跑的里程
GUI.Label(new Rect(550, 250, 150, 200),"時(shí)間:");
if (_BoolIsDisplayRunedTime)
{
GUI.Label(new Rect(700, 250, 150,200), _IntRunedTime.ToString());
}
//顯示獲得的紅寶石的數(shù)量
GUI.DrawTexture(new Rect(550, 300, 50,50), TexRedDiamonds);
if(_BoolIsDisplayRedDiamond)
{
GUI.Label(new Rect(700, 300, 150,50),_IntRedDiamondNum.ToString());
}
//顯示獲得的藍(lán)寶石的數(shù)量(測(cè)試數(shù)據(jù))
GUI.DrawTexture(new Rect(550, 350, 50,50), TexBlueDiamonds);
GUI.Label(new Rect(700, 350, 50, 50),GlobalInfoManger.IntRedDiamonds.ToString());
//顯示“重玩”,"退出"。
if (GUI.Button(new Rect((Screen.width /2 - TexRePlay.width / 2)-100, Screen.height / 2 - TexRePlay.height / 2+150,TexRePlay.width, TexRePlay.height), "",ProjectGUISkin.GetStyle("Btn_Replay")))
{
_boolRePlay = true;
}
else if (GUI.Button(newRect((Screen.width / 2 - TexRePlay.width / 2)+100, Screen.height / 2 - TexRePlay.height/ 2+150, TexRePlay.width, TexRePlay.height), "",ProjectGUISkin.GetStyle("Btn_Exit")))
{
_boolExit = true;
}
}//OnGUI_end
//邏輯處理。
void Update()
{
if(_boolRePlay)
{
//調(diào)用指定的場(chǎng)景。
GlobalInfoManger.IntGameTime =0; //時(shí)間清零
Application.LoadLevel(StrScenesName);
}
else if (_boolExit)
{
//退出游戲
Application.Quit();
}
}
}//Class_end
圖 1.2
示例 1.2 參考圖1.2進(jìn)行理解,其基本原理與示例1.1基本相同,在這就不再贅述。
對(duì)于InvokeRepeating則在項(xiàng)目中運(yùn)用的更多,請(qǐng)看如下示例代碼。
(示例 1.3)
usingUnityEngine;
usingSystem.Collections;
public classScenesManager_Level1 : MonoBehaviour {
public Transform TrnHero; //主人公位置信息
public string StrStartScenceName; //開始場(chǎng)景的名稱
//克隆道具
public GameObject Go_ScriptsObject; //腳本對(duì)象
public GameObjectGoCloneOriginal_Diamend; //克隆原型_紅寶石
public GameObjectGoCloneOriginal_Tree; //克隆原型_樹木
public GameObjectGo_CloneObj_RefPosion_Left; //克隆位置基準(zhǔn)。
public GameObjectGo_CloneObj_RefPosion_Right;
private AudioSource _ASBGMusic; //背景音樂
private AudioSource[] _ASAudioEffect; //音頻數(shù)組
private Vector3_VecHeroPositionOfOriginal; //主人公原始位置
void Start ()
{
//游戲結(jié)束
GlobalInfoManger.CurrentGameState =GameState.Prepare;
//設(shè)置音頻
SetAudio();
//主人公位置初始值
_VecHeroPositionOfOriginal = TrnHero.transform.position;
//檢測(cè)狀態(tài)信息
InvokeRepeating("CheckHeroState",1F,1F);
//動(dòng)態(tài)生成道具。(單次加載方式)
//DanymicCreateRedDiamond();
//分步加載方式
InvokeRepeating("DanymicCreateProperty",1F,1F);
}//Start_end
/// <summary>
///動(dòng)態(tài)加載各種道具
/// </summary>
private void DanymicCreateProperty()
{
//加載紅寶石
if(GlobalInfoManger.IntGameTime==1)
{
this.CreateProperty(GoCloneOriginal_Diamend,15,30,100);
}
//第二次
if (GlobalInfoManger.IntGameTime ==15)
{
//加載寶石
this.CreateProperty(GoCloneOriginal_Diamend, 20, 30, 150);
//加載樹木
this.CreateProperty(GoCloneOriginal_Tree,5, 30, 100);
}
//第三次。
if (GlobalInfoManger.IntGameTime ==20)
{
//加載地刺
//加載寶石
this.CreateProperty(GoCloneOriginal_Diamend, 50, 30,650);
//加載樹木
this.CreateProperty(GoCloneOriginal_Tree,10,30, 600);
}
}//DanymicCreateProperty_end
/// <summary>
///創(chuàng)建道具
/// </summary>
/// <paramname="goCloneOriginal">克隆原型</param>
/// <paramname="intCloneNumber">克隆數(shù)量</param>
/// <paramname="intDestroyGOTime">銷毀時(shí)間</param>
/// <paramname="intAddingGameobjectLenth">克隆對(duì)象的距離</param>
void CreateProperty(GameObjectgoCloneOriginal,int intCloneNumber,int intDestroyGOTime,intintAddingGameobjectLenth)
{
/*數(shù)據(jù)集合準(zhǔn)備 */
System.Object[] ObjArray = newSystem.Object[8];
ObjArray[0] = goCloneOriginal; //克隆的原型
ObjArray[1] = intCloneNumber; //克隆的數(shù)量
ObjArray[2] = intDestroyGOTime; //克隆體銷毀的時(shí)間
//X坐標(biāo)最小數(shù)值
ObjArray[3] =Go_CloneObj_RefPosion_Left.transform.position.x;
//X坐標(biāo)最大數(shù)值
ObjArray[4] =Go_CloneObj_RefPosion_Right.transform.position.x;
//Y坐標(biāo)
ObjArray[5] =Go_CloneObj_RefPosion_Left.transform.position.y;
//Z坐標(biāo)最小數(shù)值
ObjArray[6] =Go_CloneObj_RefPosion_Left.transform.position.z;
//Z坐標(biāo)最大數(shù)值
ObjArray[7] =Go_CloneObj_RefPosion_Left.transform.position.z + intAddingGameobjectLenth;
/*調(diào)用動(dòng)態(tài)克隆方法 */
Go_ScriptsObject.SendMessage("DynamicCreProperty", ObjArray,SendMessageOptions.DontRequireReceiver);
}
/// <summary>
///檢測(cè)主人公狀態(tài)信息
/// </summary>
void CheckHeroState()
{
//游戲時(shí)間自增
++GlobalInfoManger.IntGameTime;
//如果主人公Y軸出現(xiàn)較大的變化,判斷主人公掉下橋體,游戲結(jié)束
if (TrnHero.transform.position.y <(_VecHeroPositionOfOriginal.y-10))
{
GlobalInfoManger.CurrentGameState= GameState.GameOver;
}
//判斷游戲結(jié)束后,處理方式。
if (GlobalInfoManger.CurrentGameState== GameState.GameOver)
{
_ASBGMusic.Stop(); //關(guān)閉背景音樂
_ASAudioEffect[1].Play(); //播放GameOver 音頻
//3秒后返回開始場(chǎng)景
Invoke("ReturnStartScenes", 3F);
}
}
//設(shè)置音頻
void SetAudio()
{
//背景音樂音量大小判斷
_ASBGMusic =GameObject.Find("_AudiosManager/_AudioBGMusic").GetComponent<AudioSource>();
switch (GlobalInfoManger.ProVolumns)
{
case ProjectVlumns.None:
break;
case ProjectVlumns.NoneVolumns:
_ASBGMusic.volume = 0F;
break;
case ProjectVlumns.HalfVolumns:
_ASBGMusic.volume = 0.5F;
break;
case ProjectVlumns.FullVolumns:
_ASBGMusic.volume = 1F;
break;
default:
break;
}//switch_end
//音效處理
_ASAudioEffect =GameObject.Find("_AudiosManager/_AudioEffect").GetComponents<AudioSource>();
_ASAudioEffect[1].volume = 1F;
_ASAudioEffect[1].loop = false;
}
//返回開始開始場(chǎng)景
void ReturnStartScenes()
{
Application.LoadLevel(StrStartScenceName);
}
}//Class_end
示例 1.3 可以參考圖1.1進(jìn)行理解,基本原理如下:
以上在Start() 事件函數(shù)中定義的“CheckHeroState()”[檢測(cè)主角的狀態(tài)信息]與“DanymicCreateRedDiamond()”[動(dòng)態(tài)生成道具] 方法分別都是被InvokeRepeate 進(jìn)行循環(huán)調(diào)用,按照一定的固定時(shí)間間隔。 這里在本應(yīng)用場(chǎng)景中的以上兩個(gè)方法中由于不需要產(chǎn)生不固定的時(shí)間間隔,所以就不需要使用協(xié)程了。
最后提及一下Coroutine(協(xié)程)與InvokeRepeating(重復(fù)調(diào)用函數(shù)),在被腳本禁用的時(shí)候是不會(huì)自動(dòng)停止調(diào)用的,需要手工編寫對(duì)應(yīng)的停止調(diào)用函數(shù)進(jìn)行停止,否則會(huì)出現(xiàn)很多問題。且還要注意調(diào)用與停止調(diào)用的時(shí)機(jī)問題,我會(huì)在下一篇博客中關(guān)于討論Unity 腳本的生命周期中進(jìn)行討論,謝謝。
(跑酷游戲)源代碼下載鏈接:
http://pan.baidu.com/s/1sj8X3lV
網(wǎng)站名稱:Unity協(xié)程與調(diào)用函數(shù)的區(qū)別以及示例應(yīng)用
文章出自:http://jinyejixie.com/article38/iicssp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供電子商務(wù)、網(wǎng)站排名、自適應(yīng)網(wǎng)站、營銷型網(wǎng)站建設(shè)、全網(wǎng)營銷推廣、ChatGPT
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)