久久精品国产亚洲高清|精品日韩中文乱码在线|亚洲va中文字幕无码久|伊人久久综合狼伊人久久|亚洲不卡av不卡一区二区|精品久久久久久久蜜臀AV|国产精品19久久久久久不卡|国产男女猛烈视频在线观看麻豆

    1. <style id="76ofp"></style>

      <style id="76ofp"></style>
      <rt id="76ofp"></rt>
      <form id="76ofp"><optgroup id="76ofp"></optgroup></form>
      1. 千鋒教育-做有情懷、有良心、有品質(zhì)的職業(yè)教育機(jī)構(gòu)

        手機(jī)站
        千鋒教育

        千鋒學(xué)習(xí)站 | 隨時(shí)隨地免費(fèi)學(xué)

        千鋒教育

        掃一掃進(jìn)入千鋒手機(jī)站

        領(lǐng)取全套視頻
        千鋒教育

        關(guān)注千鋒學(xué)習(xí)站小程序
        隨時(shí)隨地免費(fèi)學(xué)習(xí)課程

        當(dāng)前位置:首頁(yè)  >  技術(shù)干貨  > 一節(jié)課徹底掌握Unity中協(xié)程的用法

        一節(jié)課徹底掌握Unity中協(xié)程的用法

        來(lái)源:千鋒教育
        發(fā)布人:syq
        時(shí)間: 2022-06-08 13:57:00 1654667820

          文章目錄

          一、前言

          二、學(xué)習(xí)使用協(xié)程

          1.首先定義多個(gè)定時(shí)器,去實(shí)現(xiàn)游戲中的邏輯...

          2.案例演示

          3.開(kāi)啟和終止協(xié)程

          4.協(xié)程的返回值

          5.案例應(yīng)用

          三、總結(jié)

          前言

          協(xié)程在Unity開(kāi)發(fā)中非常重要,但注意:協(xié)程跟多線程沒(méi)有任何關(guān)系,不要將兩者混為一談,接下來(lái)就跟大家分享一下我對(duì)協(xié)程的理解及用法!

        Unity中協(xié)程的用法

          一、協(xié)程是什么?

          協(xié)程是一段在主線程中執(zhí)行的代碼邏輯,協(xié)程不是多線程。Unity的協(xié)程在每幀結(jié)束后去檢測(cè)yiled的條件是否滿足。

          二、學(xué)習(xí)使用協(xié)程

          1.首先定義多個(gè)定時(shí)器,去實(shí)現(xiàn)游戲中的邏輯...

          代碼如下:

          float timer1 = 3f;

          float timer2 = 5f;

          float timer3 = 8f;

          void Update()

            {

                timer1 -= Time.deltaTime;

                if (timer1 <= 0)

                {

                    Debug.Log("3s過(guò)后...");

                    timer1 = 3f;

                }

            }

          相信大家都寫過(guò)類似代碼,這種代碼如果項(xiàng)目中需要多個(gè)定時(shí)器時(shí),會(huì)顯得非常臃腫,并且我們經(jīng)常忘記做一件事情,比如忘記充值定時(shí)器...

          我們都學(xué)過(guò)循環(huán),for循環(huán)中是將變量i定義為局部變量,封裝成一個(gè)代碼塊,那我們是否可以將定時(shí)器也封裝成一個(gè)代碼塊呢?如果可以的話,那么代碼應(yīng)該是這樣的:

         for (float timer = 3; timer >= 0; timer -= Time.deltaTime)

                {

                    

                }

          現(xiàn)在每一個(gè)計(jì)時(shí)器變量都成為for循環(huán)的一部分了,這看上去好多了,而且我不需要去單獨(dú)設(shè)置每一個(gè)迭代變量。 但是這段代碼放在哪里去執(zhí)行呢?start?update?顯然都不可以,所以恰好協(xié)程可以做到這一點(diǎn)。我們回顧一下協(xié)程的概念:

          為了能在連續(xù)的多幀中(在這個(gè)例子中,3秒鐘等同于很多幀)調(diào)用該方法,Unity必須通過(guò)某種方式來(lái)存儲(chǔ)這個(gè)方法的狀態(tài),

          -這是通過(guò)IEnumerator 中使用yield return語(yǔ)句得到的返回值,當(dāng)你“yield”一個(gè)方法時(shí),你相當(dāng)于說(shuō)了,“現(xiàn)在暫停這個(gè)方法,

          -然后在下一幀中從這里繼續(xù)執(zhí)行!”。

          注意:用0或者null來(lái)yield的意思是告訴協(xié)程等待下一幀,直到繼續(xù)執(zhí)行為止。

          當(dāng)然,同樣的你可以繼續(xù)yield其他協(xié)程,我會(huì)在下一個(gè)教程中講到這些。

          代碼如下:

            IEnumerator CountDown(){

                for (float timer = 3; timer >= 0; timer -= Time.deltaTime)

                {

                    yield return 0;//現(xiàn)在停止這個(gè)方法,然后在下一幀中從這里繼續(xù)執(zhí)行!

                }

                Debug.Log("3s以后...");

            }

          2.案例演示

          /*

          * 接下來(lái)通過(guò)實(shí)例

          * 1.實(shí)現(xiàn)打印5次--我要學(xué)游戲開(kāi)發(fā)!

          * 2.實(shí)現(xiàn)將這5次輸出分到每一幀里去實(shí)現(xiàn):每幀打印1次,共打印5次!

          * 3.每一幀輸出“我要學(xué)游戲開(kāi)發(fā)!”,無(wú)限循環(huán)。。。

          通過(guò)在一個(gè)while循環(huán)中使用yield,你可以得到一個(gè)無(wú)限循環(huán)的協(xié)程,這幾乎就跟一個(gè)Update()循環(huán)等同。。。

          */

          2.代碼如下:

          IEnumerator SayHello5Times()

            {

                for (int i = 0; i < 5; i++)

                {

                    Debug.Log("我要學(xué)游戲開(kāi)發(fā)!");

                    yield return 0;

                }

          3.類似Update,代碼如下:

         IEnumerator SayHello5Times()

         {

              while (true)

                {

                    //1.輸出結(jié)果

                    Debug.Log("我要學(xué)游戲開(kāi)發(fā)!");

                    //2.等待下一幀

                    yield return 0;

                }

          //1.輸出結(jié)果

          Debug.Log("我要學(xué)游戲開(kāi)發(fā)!");

          //2.等待下一幀

          //3. 這里永遠(yuǎn)沒(méi)有機(jī)會(huì)執(zhí)行

          }

          但是跟Update()不一樣的是,你可以在協(xié)程中做一些更有趣的事:

          接下來(lái)做一個(gè)定時(shí)器 每隔幾秒完成某一件事

            IEnumerator CountSeconds()

            {

                int seconds = 0;

                while (true)

                {

                    for (float timer = 0; timer < 1; timer += Time.deltaTime)

                    {

                        yield return 0;

                    }

                    seconds++;

                    Debug.Log("自協(xié)程啟動(dòng)以來(lái)已經(jīng)過(guò)了"+ seconds+"秒");

                }

            }

          這個(gè)方法突出了協(xié)程一個(gè)非??岬牡胤剑悍椒ǖ臓顟B(tài)被存儲(chǔ)了,這使得方法中定義的這些變量都會(huì)保存它們的值,即使是在不同的幀中。還記得這個(gè)教程開(kāi)始時(shí)那些煩人的計(jì)時(shí)器變量嗎?通過(guò)協(xié)程,我們?cè)僖膊恍枰獡?dān)心它們了,只需要把變量直接放到方法里面!實(shí)際還有更優(yōu)雅的實(shí)現(xiàn)方式!稍后會(huì)跟大家講到。

          3.開(kāi)啟和終止協(xié)程

          之前,我們已經(jīng)學(xué)過(guò)了通過(guò) StartCoroutine()方法來(lái)開(kāi)始一個(gè)協(xié)程。

          如果我們想要終止所有的協(xié)程,可以通過(guò)StopAllCoroutines()方法來(lái)實(shí)現(xiàn),

          注意,這只會(huì)終止在調(diào)用該方法的對(duì)象中開(kāi)始的協(xié)程,對(duì)于其他的MonoBehavior類中運(yùn)行的協(xié)程不起作用。

          那我們?cè)趺唇K止其中的一個(gè)協(xié)程呢?在這個(gè)例子里,這是不能的,如果你想要終止某一個(gè)特定的協(xié)程,

          那么你必須得在開(kāi)始協(xié)程的時(shí)候?qū)⑺姆椒鳛樽址拖襁@樣:

          1、以字符串開(kāi)啟/關(guān)閉,缺點(diǎn):只能有一個(gè)參數(shù)

                StartCoroutine("FirstTimer");

                StopCoroutine("FirstTimer”);

          2、開(kāi)啟帶有參數(shù)的協(xié)程的兩種方式:

                StartCoroutine(Sayhi("hi")) 

                StartCoroutine("Sayhi","hi")

          3、如何終止多個(gè)參數(shù)的協(xié)程呢?接受返回值

            Coroutine stopCor_2 = StartCoroutine(Cor_2());

            StopCoroutine(stopCor_2);

          4、StopAllCoroutines

          5、通知禁用或者銷毀方式

              gameObject.SetActive(false); 

              //通過(guò)銷毀游戲?qū)ο蠓绞胶徒猛Ч?/span>

              //Destroy(gameobject)

          4.協(xié)程的返回值

          協(xié)程一旦被開(kāi)啟后 總是試圖將方法內(nèi)的代碼執(zhí)行完 之后停止

          1.在此之前,我們yield的時(shí)候總是用0(或者null),僅僅告訴程序在繼續(xù)執(zhí)行前等待下一幀。協(xié)程最強(qiáng)大的一個(gè)功能就是它們可以通過(guò)使用yield語(yǔ)句來(lái)相互嵌套。

          2.yield return new WaitForSeconds(n) 表示在n秒后執(zhí)行后面的代碼 但是會(huì)收到time.timescale 影響 ,如下代碼:

          //隔一定時(shí)間完成某件事

            IEnumerator SaySomeThings()

            {

                Debug.Log("協(xié)程開(kāi)始執(zhí)行");

                yield return StartCoroutine(Wait(1.0f));

                Debug.Log("距離上一條消息已經(jīng)過(guò)去1秒了");

                yield return StartCoroutine(Wait(2.5f));

                Debug.Log("距離上一條消息已經(jīng)過(guò)去2.5秒了");

            }

          上述方法用了yield,但它并沒(méi)有用0或者null,而是用了Wait()來(lái)yield,這相當(dāng)于是說(shuō),“不再繼續(xù)執(zhí)行本程序,直到Wait程序結(jié)束”。

          等待的方法還可以使用下面方式來(lái)實(shí)現(xiàn):

            IEnumerator Wait(float duration)

            {

                for (float timer = 0; timer < duration; timer += Time.deltaTime)

                    yield return 0;

            }

          3.在協(xié)程內(nèi) 如果遇到y(tǒng)ield return StartCoroutine(test) 剩余的代碼將在子協(xié)程執(zhí)行完畢后才能繼續(xù)執(zhí)行

          4.如果遇到 yield return new WaitForFixedUpdate 表示剩余代碼將在FixedUpdate 執(zhí)行完畢后執(zhí)行

          5.如果遇到 yield return WWW 等待一個(gè)網(wǎng)絡(luò)請(qǐng)求完成后繼續(xù)向下執(zhí)行

          6.如果遇到 yield return gameObject; 表示在gameobj不為空時(shí)向下執(zhí)行

          5.案例應(yīng)用

          控制對(duì)象行為的例子

          在最后一個(gè)例子中,我們就來(lái)看看協(xié)程如何像創(chuàng)建方便的計(jì)時(shí)器一樣來(lái)控制對(duì)象行為。協(xié)程不僅僅可以使用計(jì)數(shù)的時(shí)間來(lái)yield,它還能很巧妙地利用任何條件。將它與嵌套結(jié)合使用,你會(huì)得到控制游戲?qū)ο鬆顟B(tài)的最強(qiáng)大工具。運(yùn)動(dòng)到某一位置,對(duì)于下面這個(gè)簡(jiǎn)單腳本組件,我們可以在Inspector面板中給targetPosition和moveSpeed變量賦值,程序運(yùn)行的時(shí)候,該對(duì)象就會(huì)在協(xié)程的作用下,以我們給定的速度運(yùn)動(dòng)到給定的位置。

          代碼如下:

        public Vector3 targetPosition;  

            public float moveSpeed;

            void Start1()

            {

                StartCoroutine(MoveToPosition(targetPosition));

            }

         

            IEnumerator MoveToPosition(Vector3 target)

            {

                while (transform.position != target)

                {

                    transform.position = Vector3.MoveTowards(transform.position, target, moveSpeed * Time.deltaTime);

                    yield return 0;

                }

            }

          這樣,這個(gè)程序并沒(méi)有通過(guò)一個(gè)計(jì)時(shí)器或者無(wú)限循環(huán),而是根據(jù)對(duì)象是否到達(dá)指定位置來(lái)yield。

          我們可以讓運(yùn)動(dòng)到某一位置的程序做更多,不僅僅是一個(gè)指定位置,我們還可以通過(guò)數(shù)組來(lái)給它賦值更多的位置,通過(guò)MoveToPosition() ,我們可以讓它在這些點(diǎn)之間持續(xù)運(yùn)動(dòng)。

          代碼如下:

         public Vector3[] path;  

         

            void Start2()

            {

                StartCoroutine(MoveOnPath(true));

            }

         

            IEnumerator MoveOnPath(bool loop)

            {

                do

                {

                    foreach (var point in path)

                        yield return StartCoroutine(MoveToPosition(point));

                }

                while (loop);

            }

          還可以加一個(gè)布爾變量,你可以控制在對(duì)象運(yùn)動(dòng)到最后一個(gè)點(diǎn)時(shí)是否要進(jìn)行循環(huán)。

          課堂練習(xí):嘗試讓物體在某個(gè)點(diǎn)停留3s

          如果把Wait()程序加進(jìn)來(lái),這樣就能讓我們的對(duì)象在某個(gè)點(diǎn)就可以選擇是否暫停下來(lái),就像一個(gè)正在巡邏的AI守衛(wèi)一樣,并且這種實(shí)現(xiàn)方式看起來(lái)非常優(yōu)雅!

          三、總結(jié)

          l 多個(gè)協(xié)程可以同時(shí)運(yùn)行,它們會(huì)根據(jù)各自的啟動(dòng)順序來(lái)更新;

          l 協(xié)程可以嵌套任意多層(在這個(gè)例子中我們只嵌套了一層);

          l 如果你想讓多個(gè)腳本訪問(wèn)一個(gè)協(xié)程,那么你可以定義靜態(tài)的協(xié)程;

          l 協(xié)程不是多線程(盡管它們看上去是這樣的),它們運(yùn)行在同一線程中,跟普通的腳本一樣;

          l 如果你的程序需要進(jìn)行大量的計(jì)算,那么可以考慮在一個(gè)隨時(shí)間進(jìn)行的協(xié)程中處理它們;

          l IEnumerator類型的方法不能帶ref或者out型的參數(shù),但可以帶被傳遞的引用;

          l 協(xié)程有多種開(kāi)啟和終止的方法,但是最好用哪種方式開(kāi)啟,就是用哪種方式終止。

          更多關(guān)于“Unity”的問(wèn)題,歡迎咨詢千鋒教育在線名師。千鋒教育多年辦學(xué),課程大綱緊跟企業(yè)需求,更科學(xué)更嚴(yán)謹(jǐn),每年培養(yǎng)泛IT人才近2萬(wàn)人。不論你是零基礎(chǔ)還是想提升,都可以找到適合的班型,千鋒教育隨時(shí)歡迎你來(lái)試聽(tīng)。

        tags:
        聲明:本站稿件版權(quán)均屬千鋒教育所有,未經(jīng)許可不得擅自轉(zhuǎn)載。
        10年以上業(yè)內(nèi)強(qiáng)師集結(jié),手把手帶你蛻變精英
        請(qǐng)您保持通訊暢通,專屬學(xué)習(xí)老師24小時(shí)內(nèi)將與您1V1溝通
        免費(fèi)領(lǐng)取
        今日已有369人領(lǐng)取成功
        劉同學(xué) 138****2860 剛剛成功領(lǐng)取
        王同學(xué) 131****2015 剛剛成功領(lǐng)取
        張同學(xué) 133****4652 剛剛成功領(lǐng)取
        李同學(xué) 135****8607 剛剛成功領(lǐng)取
        楊同學(xué) 132****5667 剛剛成功領(lǐng)取
        岳同學(xué) 134****6652 剛剛成功領(lǐng)取
        梁同學(xué) 157****2950 剛剛成功領(lǐng)取
        劉同學(xué) 189****1015 剛剛成功領(lǐng)取
        張同學(xué) 155****4678 剛剛成功領(lǐng)取
        鄒同學(xué) 139****2907 剛剛成功領(lǐng)取
        董同學(xué) 138****2867 剛剛成功領(lǐng)取
        周同學(xué) 136****3602 剛剛成功領(lǐng)取
        相關(guān)推薦HOT
        藍(lán)v抖音小店怎么開(kāi)通店鋪

        藍(lán)v抖音小店是一個(gè)非常熱門的電商平臺(tái),它可以讓賣家在抖音上開(kāi)設(shè)自己的店鋪,從而出售自己的商品。隨著抖音的不斷發(fā)展壯大,越來(lái)越多的賣家希...詳情>>

        2023-10-08 14:51:53
        抖音小店怎么更改類目名稱

        抖音小店是現(xiàn)在非?;馃岬囊环N網(wǎng)店形態(tài),許多小生意也從中獲得了收益。但是隨著經(jīng)營(yíng)時(shí)間的增長(zhǎng),小店也需要對(duì)自己的類目名稱進(jìn)行更改,因?yàn)檫@可...詳情>>

        2023-10-08 14:46:50
        抖音小店怎么合作賣貨

        抖音小店作為一種新型的電商形式,近年來(lái)在國(guó)內(nèi)市場(chǎng)上逐漸火熱起來(lái),成為了許多年輕人賺取收入的途徑之一。因?yàn)槎兑糇鳛楫?dāng)前最流行的短視頻平臺(tái)...詳情>>

        2023-10-08 14:35:49
        抖音小店運(yùn)營(yíng)和天貓區(qū)別是什么呢

        隨著社交媒體的廣泛應(yīng)用,抖音小店開(kāi)始走進(jìn)人們的生活,成為越來(lái)越多人的購(gòu)物選擇之一。而天貓作為國(guó)內(nèi)最具影響力的電商平臺(tái)之一,是許多電商從...詳情>>

        2023-10-08 14:23:10
        抖音小店在哪個(gè)界面進(jìn)入店鋪?lái)?yè)面

        抖音小店,是指在抖音平臺(tái)上開(kāi)設(shè)的個(gè)人或企業(yè)店鋪。隨著抖音用戶數(shù)的不斷增加,抖音小店越來(lái)越受到用戶的歡迎和喜愛(ài)。但是,如何進(jìn)入抖音小店的...詳情>>

        2023-10-08 14:21:20
        岱山县| 广灵县| 延津县| 石阡县| 环江| 常宁市| 潞城市| 德州市| 龙泉市| 荆州市| 罗田县| 固阳县| 岑巩县| SHOW| 浏阳市| 呼玛县| 巫山县| 绵阳市| 筠连县| 老河口市| 衡阳市| 苍山县| 申扎县| 德格县| 黑龙江省| 右玉县| 柳林县| 和平县| 防城港市| 镶黄旗| 太原市| 额敏县| 纳雍县| 会东县| 景谷| 翁牛特旗| 共和县| 射阳县| 西乡县| 大化| 宁安市|