溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Unity中協(xié)程IEnumerator如何使用

發(fā)布時(shí)間:2022-06-13 09:43:43 來源:億速云 閱讀:169 作者:iii 欄目:開發(fā)技術(shù)

本文小編為大家詳細(xì)介紹“Unity中協(xié)程IEnumerator如何使用”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“Unity中協(xié)程IEnumerator如何使用”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識(shí)吧。

在Unity中,一般的方法都是順序執(zhí)行的,一般的方法也都是在一幀中執(zhí)行完畢的,當(dāng)我們所寫的方法需要耗費(fèi)一定時(shí)間時(shí),便會(huì)出現(xiàn)幀率下降,畫面卡頓的現(xiàn)象。當(dāng)我們調(diào)用一個(gè)方法想要讓一個(gè)物體緩慢消失時(shí),除了在Update中執(zhí)行相關(guān)操作外,Unity還提供了更加便利的方法,這便是協(xié)程。

在通常情況下,如果我們想要讓一個(gè)物體逐漸消失,我們希望方法可以一次調(diào)用便可在程序后續(xù)執(zhí)行中實(shí)現(xiàn)我們想要的效果。

我們希望代碼可以寫成如下所示:

void Fade() 
{
    for (float f = 1f; f >= 0; f -= 0.1f) 
    {
        Color c = renderer.material.color;
        c.a = f;
        renderer.material.color = c;
    }
}

然而該方法在調(diào)用時(shí)將在一幀中執(zhí)行完畢,無法實(shí)現(xiàn)預(yù)期的效果。如果將該方法改寫并放到Update函數(shù)中可實(shí)現(xiàn)我們預(yù)期的效果,但是還不夠優(yōu)雅。

float time = 0f;
float fadeTime = 2f;
void Fade() 
{
    time += Time.dealttime;
    Color c = renderer.material.color;
    c.a = 1f - time/fadeTime;
    renderer.material.color = c;
}

Unity中的協(xié)程方法通過yield這個(gè)特殊的屬性可以在任何位置、任意時(shí)刻暫停。也可以在指定的時(shí)間或事件后繼續(xù)執(zhí)行,而不影響上一次執(zhí)行的就結(jié)果,提供了極大地便利性和實(shí)用性。
協(xié)程在每次執(zhí)行時(shí)都會(huì)新建一個(gè)(偽)新線程來執(zhí)行,而不會(huì)影響主線程的執(zhí)行情況。

正如上邊的方法,我們使用協(xié)程可以更加方便的實(shí)現(xiàn)我們想要的效果。

void Fade() 
{
    for (float f = 1f; f >= 0; f -= 0.1f) 
    {
        Color c = renderer.material.color;
        c.a = f;
        renderer.material.color = c;
        yield return null;//下一幀繼續(xù)執(zhí)行for循環(huán)
        yield return new WaitForSeconds(0.1f);//0.1秒后繼續(xù)執(zhí)行for循環(huán)
    }
}

我們通過StartCoroutine()函數(shù)來調(diào)用協(xié)程函數(shù)。

值得注意的是,協(xié)程并不會(huì)在Unity中開辟新的線程來執(zhí)行,其執(zhí)行仍然發(fā)生在主線程中。當(dāng)我們有較為耗時(shí)的操作時(shí),可以將該操作分散到幾幀或者幾秒內(nèi)完成,而不用在一幀內(nèi)等這個(gè)操作完成后再執(zhí)行其他操作。
如我們需要執(zhí)行一個(gè)循環(huán):

IEnumerator CaculateResult()
{
    for (int i = 0; i < 10000; i++)
    {
        //內(nèi)部循環(huán)計(jì)算
        //在這里的yield會(huì)讓改內(nèi)部循環(huán)計(jì)算每幀執(zhí)行一次,而不會(huì)等待10000次循環(huán)結(jié)束后再跳出
        //yield return null;
    }
    //如果取消內(nèi)部的yield操作,僅在for循環(huán)外邊寫yield操作,則會(huì)執(zhí)行完10000次循環(huán)后再結(jié)束,相當(dāng)于直接調(diào)用了一個(gè)函數(shù),而非協(xié)程。
    //yield return null;
}

調(diào)用協(xié)程的方法有兩種,分別是StartCoroutine(/這里直接調(diào)用方法,添加參數(shù)/),另一種是StartCoroutine(/這里填寫”字符串的方法名字”,方法參數(shù)/)。第一種方法的優(yōu)勢(shì)在于可以調(diào)用多個(gè)參數(shù)的方法,后一種方法只能調(diào)用不含參數(shù)或只包含一個(gè)參數(shù)的協(xié)程方法。但是第一種方法不能通過StopCoroutine(/這里填寫”字符串的方法名”/)來結(jié)束協(xié)程,只能通過StopAllCoroutines來結(jié)束。后一種則可以通過StopCoroutine來結(jié)束對(duì)正在執(zhí)行的協(xié)程的調(diào)用。

協(xié)程在實(shí)現(xiàn)過程中我們需要注意yield調(diào)用的時(shí)機(jī),執(zhí)行較為復(fù)雜的計(jì)算時(shí),如果在時(shí)間上沒有嚴(yán)格的先后順序,我們可以每幀執(zhí)行一次循環(huán)來完成計(jì)算,或者每幀執(zhí)行指定次數(shù)的循環(huán)來防止在程序運(yùn)行中出現(xiàn)的卡頓現(xiàn)象。

yield return的介紹:

yield return null; // 下一幀再執(zhí)行后續(xù)代碼
yield return 0; //下一幀再執(zhí)行后續(xù)代碼
yield return 6;//(任意數(shù)字) 下一幀再執(zhí)行后續(xù)代碼
yield break; //直接結(jié)束該協(xié)程的后續(xù)操作
yield return asyncOperation;//等異步操作結(jié)束后再執(zhí)行后續(xù)代碼
yield return StartCoroution(/*某個(gè)協(xié)程*/);//等待某個(gè)協(xié)程執(zhí)行完畢后再執(zhí)行后續(xù)代碼
yield return WWW();//等待WWW操作完成后再執(zhí)行后續(xù)代碼
yield return new WaitForEndOfFrame();//等待幀結(jié)束,等待直到所有的攝像機(jī)和GUI被渲染完成后,在該幀顯示在屏幕之前執(zhí)行
yield return new WaitForSeconds(0.3f);//等待0.3秒,一段指定的時(shí)間延遲之后繼續(xù)執(zhí)行,在所有的Update函數(shù)完成調(diào)用的那一幀之后(這里的時(shí)間會(huì)受到Time.timeScale的影響);
yield return new WaitForSecondsRealtime(0.3f);//等待0.3秒,一段指定的時(shí)間延遲之后繼續(xù)執(zhí)行,在所有的Update函數(shù)完成調(diào)用的那一幀之后(這里的時(shí)間不受到Time.timeScale的影響);
yield return WaitForFixedUpdate();//等待下一次FixedUpdate開始時(shí)再執(zhí)行后續(xù)代碼
yield return new WaitUntil()//將協(xié)同執(zhí)行直到 當(dāng)輸入的參數(shù)(或者委托)為true的時(shí)候....如:yield return new WaitUntil(() => frame >= 10);
yield return new WaitWhile()//將協(xié)同執(zhí)行直到 當(dāng)輸入的參數(shù)(或者委托)為false的時(shí)候.... 如:yield return new WaitWhile(() => frame < 10);

當(dāng)某一個(gè)腳本中的協(xié)程在執(zhí)行過程中,如果我們將該腳本的enable設(shè)置為false,協(xié)程不會(huì)停止。只有將掛載該腳本的物體設(shè)置為SetActive(false)時(shí)才會(huì)停止。

Unity在調(diào)用StartCoroutine()后不會(huì)等待協(xié)程中的內(nèi)容返回,會(huì)立即執(zhí)行后續(xù)代碼。

讀到這里,這篇“Unity中協(xié)程IEnumerator如何使用”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識(shí)點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過才能領(lǐng)會(huì),如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI