99国产欧美另娄久久久精品_国内自拍农村少妇在线观看_久久亚洲道色宗和久久_日本aⅴ大伊香蕉精品视频_亚洲国产欧美日韩欧美特级_日本视频免费在线观看

  • 您的位置:首頁 > 新聞動態(tài) > Unity3D

    Unity3D協(xié)程Coroutine解析

    2019/1/9??????點擊:

    本文只是從Unity的角度去分析理解協(xié)程的內(nèi)部運行原理,而不是從C#底層的語法實現(xiàn)來介紹(后續(xù)有需要再進行介紹),一共分為三部分:

    1. 線程(Thread)和協(xié)程(Coroutine)

    使用協(xié)程的作用一共有兩點:1)延時(等待)一段時間執(zhí)行代碼;2)等某個操作完成之后再執(zhí)行后面的代碼??偨Y(jié)起來就是一句話:控制代碼在特定的時機執(zhí)行。 很多初學(xué)者,都會下意識地覺得協(xié)程是異步執(zhí)行的,都會覺得協(xié)程是C# 線程的替代品,是Unity不使用線程的解決方案。 所以首先,請你牢記:協(xié)程不是線程,也不是異步執(zhí)行的。協(xié)程和 MonoBehaviour 的 Update函數(shù)一樣也是在MainThread中執(zhí)行的。使用協(xié)程你不用考慮同步和鎖的問題。

    2. Unity中協(xié)程的執(zhí)行原理

    UnityGems.com給出了協(xié)程的定義: A coroutine is a function that is executed partially and, presuming suitable conditions are met, will be resumed at some point in the future until its work is done. 即協(xié)程是一個分部執(zhí)行,遇到條件(yield return 語句)會掛起,直到條件滿足才會被喚醒繼續(xù)執(zhí)行后面的代碼。 Unity在每一幀(Frame)都會去處理對象上的協(xié)程。Unity主要是在Update后去處理協(xié)程(檢查協(xié)程的條件是否滿足),但也有寫特例: 從上圖的剖析就明白,協(xié)程跟Update()其實一樣的,都是Unity每幀對會去處理的函數(shù)(如果有的話)。如果MonoBehaviour 是處于激活(active)狀態(tài)的而且yield的條件滿足,就會協(xié)程方法的后面代碼。還可以發(fā)現(xiàn):如果在一個對象的前期調(diào)用協(xié)程,協(xié)程會立即運行到第一個 yield return 語句處,如果是 yield return null ,就會在同一幀再次被喚醒。如果沒有考慮這個細(xì)節(jié)就會出現(xiàn)一些奇怪的問題『1』。 『1』注 圖和結(jié)論都是從UnityGems.com 上得來的,經(jīng)過下面的驗證發(fā)現(xiàn)與實際不符,D.S.Qiu用的是Unity 4.3.4f1 進行測試的。 經(jīng)過測試驗證,協(xié)程至少是每幀的LateUpdate()后去運行。

    下面使用 yield return new WaitForSeconds(1f); 在Start,Update 和 LateUpdate 中分別進行測試:

    using UnityEngine;
    using System.Collections;
    
    public class TestCoroutine : MonoBehaviour {
    
        private bool isStartCall = false;  //Makesure Update() and LateUpdate() Log only once
        private bool isUpdateCall = false;
        private bool isLateUpdateCall = false;
        // Use this for initialization
        void Start () {
            if (!isStartCall)
            {
                Debug.Log("Start Call Begin");
                StartCoroutine(StartCoutine());
                Debug.Log("Start Call End");
                isStartCall = true;
            }
    
        }
        IEnumerator StartCoutine()
        {
    
            Debug.Log("This is Start Coroutine Call Before");
            yield return null;
            Debug.Log("This is Start Coroutine Call After");
    
        }
        // Update is called once per frame
        void Update () {
            if (!isUpdateCall)
            {
                Debug.Log("Update Call Begin");
                StartCoroutine(UpdateCoutine());
                Debug.Log("Update Call End");
                isUpdateCall = true;
            }
        }
        IEnumerator UpdateCoutine()
        {
            Debug.Log("This is Update Coroutine Call Before");
            yield return null;
            Debug.Log("This is Update Coroutine Call After");
        }
        void LateUpdate()
        {
            if (!isLateUpdateCall)
            {
                Debug.Log("LateUpdate Call Begin");
                StartCoroutine(LateCoutine());
                Debug.Log("LateUpdate Call End");
                isLateUpdateCall = true;
            }
        }
        IEnumerator LateCoutine()
        {
            Debug.Log("This is Late Coroutine Call Before");
            yield return null;
            Debug.Log("This is Late Coroutine Call After");
        }
    }
    得到日志輸入結(jié)果如下:



    然后將yield return new WaitForSeconds(1f);改為 yield return null; 發(fā)現(xiàn)日志輸入結(jié)果和上面是一樣的,沒有出現(xiàn)上面說的情況.

    MonoBehaviour 沒有針對特定的協(xié)程提供Stop方法,其實不然,可以通過MonoBehaviour enabled = false 或者 gameObject.active = false 就可以停止協(xié)程的執(zhí)行『2』。

    經(jīng)過驗證,『2』的結(jié)論也是錯誤的,正確的結(jié)論是,MonoBehaviour.enabled = false 協(xié)程會照常運行,但 gameObject.SetActive(false) 后協(xié)程卻全部停止,即使在Inspector把 gameObject 激活還是沒有繼續(xù)執(zhí)行:

    using UnityEngine;
    using System.Collections;
    
    public class TestCoroutine : MonoBehaviour {
    
      private bool isStartCall = false;  //Makesure Update() and LateUpdate() Log only once
      private bool isUpdateCall = false;
      private bool isLateUpdateCall = false;
      // Use this for initialization
      void Start () {
        if (!isStartCall)
        {
          Debug.Log("Start Call Begin");
          StartCoroutine(StartCoutine());
          Debug.Log("Start Call End");
          isStartCall = true;
        }
    
      }
      IEnumerator StartCoutine()
      {
    
        Debug.Log("This is Start Coroutine Call Before");
        yield return new WaitForSeconds(1f);
        Debug.Log("This is Start Coroutine Call After");
    
      }
      // Update is called once per frame
      void Update () {
        if (!isUpdateCall)
        {
          Debug.Log("Update Call Begin");
          StartCoroutine(UpdateCoutine());
          Debug.Log("Update Call End");
          isUpdateCall = true;
          this.enabled = false;
          //this.gameObject.SetActive(false);
        }
      }
      IEnumerator UpdateCoutine()
      {
        Debug.Log("This is Update Coroutine Call Before");
        yield return new WaitForSeconds(1f);
        Debug.Log("This is Update Coroutine Call After");
        yield return new WaitForSeconds(1f);
        Debug.Log("This is Update Coroutine Call Second");
      }
      void LateUpdate()
      {
        if (!isLateUpdateCall)
        {
          Debug.Log("LateUpdate Call Begin");
          StartCoroutine(LateCoutine());
          Debug.Log("LateUpdate Call End");
          isLateUpdateCall = true;
    
        }
      }
      IEnumerator LateCoutine()
      {
        Debug.Log("This is Late Coroutine Call Before");
        yield return null;
        Debug.Log("This is Late Coroutine Call After");
      }
    }
    先在Update中調(diào)用 this.enabled = false; 得到的結(jié)果:



    然后把 this.enabled = false; 注釋掉,換成 this.gameObject.SetActive(false); 得到的結(jié)果如下:

    整理得到 :通過設(shè)置MonoBehaviour腳本的enabled對協(xié)程是沒有影響的,但如果 gameObject.SetActive(false) 則已經(jīng)啟動的協(xié)程則完全停止了,即使在Inspector把gameObject 激活還是沒有繼續(xù)執(zhí)行。也就說協(xié)程雖然是在MonoBehvaviour啟動的(StartCoroutine)但是協(xié)程函數(shù)的地位完全是跟MonoBehaviour是一個層次的,不受MonoBehaviour的狀態(tài)影響,但跟MonoBehaviour腳本一樣受gameObject 控制,也應(yīng)該是和MonoBehaviour腳本一樣每幀“輪詢” yield 的條件是否滿足。


    yield 后面可以有的表達(dá)式:

    a) null - the coroutine executes the next time that it is eligible 

     b) WaitForEndOfFrame - the coroutine executes on the frame, after all of the rendering and GUI is complete 

     c) WaitForFixedUpdate - causes this coroutine to execute at the next physics step, after all physics is calculated 

     d) WaitForSeconds - causes the coroutine not to execute for a given game time period 

     e) WWW - waits for a web request to complete (resumes as if WaitForSeconds or null) 

     f) Another coroutine - in which case the new coroutine will run to completion before the yielder is resumed

    值得注意的是 WaitForSeconds()受Time.timeScale影響,當(dāng)Time.timeScale = 0f 時,yield return new WaitForSecond(x) 將不會滿足。

    3. IEnumerator & Coroutine

    協(xié)程其實就是一個IEnumerator(迭代器),IEnumerator 接口有兩個方法 Current 和 MoveNext() ,前面介紹的TaskManager就是利用者兩個方法對協(xié)程進行了管理,這里在介紹一個協(xié)程的交叉調(diào)用類 Hijack:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    
    [RequireComponent(typeof(Text))]
    public class HiJack : MonoBehaviour {
    
        //This will hold the counting up coroutine
        IEnumerator _countUp;
        //This will hold the counting down coroutine
        IEnumerator _countDown;
        //This is the coroutine we are currently
        //hijacking
        IEnumerator _current;
    
        //A value that will be updated by the coroutine
        //that is currently running
        int value = 0;
    
        void Start()
        {
            //Create our count up coroutine
            _countUp = CountUp();
            //Create our count down coroutine
            _countDown = CountDown();
            //Start our own coroutine for the hijack
            StartCoroutine(DoHijack());
        }
    
        void Update()
        {
            //Show the current value on the screen
            GetComponent().text = value.ToString ();
        }
    
        void OnGUI()
        {
            //Switch between the different functions
            if(GUILayout.Button("Switch functions"))
            {
                if(_current == _countUp)
                    _current = _countDown;
                else
                    _current = _countUp;
            }
        }
    
        IEnumerator DoHijack()
        {
            while(true)
            {
                //Check if we have a current coroutine and MoveNext on it if we do
                if(_current != null && _current.MoveNext())
                {
                    //Return whatever the coroutine yielded, so we will yield the
                    //same thing
                    yield return _current.Current;
                }
                else
                    //Otherwise wait for the next frame
                    yield return null;
            }
        }
    
        IEnumerator CountUp()
        {
            //We have a local increment so the routines
            //get independently faster depending on how
            //long they have been active
            float increment = 0;
            while(true)
            {
                //Exit if the Q button is pressed
                if(Input.GetKey(KeyCode.Q))
                    break;
                increment+=Time.deltaTime;
                value += Mathf.RoundToInt(increment);
                yield return null;
            }
        }
    
        IEnumerator CountDown()
        {
            float increment = 0f;
            while(true)
            {
                if(Input.GetKey(KeyCode.Q))
                    break;
                increment+=Time.deltaTime;
                value -= Mathf.RoundToInt(increment);
                //This coroutine returns a yield instruction
                yield return new WaitForSeconds(0.1f);
            }
        }
    }
    上面的代碼實現(xiàn)是兩個協(xié)程交替調(diào)用。



    主站蜘蛛池模板: 日韩一二三区在线观看_肥白大屁股BBWBBWHD_久久国产福利国产秒拍_日本XXXX色视频在线播放_久久久久久久久久97_密桃视频成人免费_大白天情侣对白肉麻的很_免费播放一级毛片 | 亚洲AV成人无码人在线观看堂_疾速追杀4免费高清完整在线观看_亚洲国产初高中生女AV_末成年女AV片一区二区丫_日韩欧美一级二级_成全免费高清观看_午夜免费视频福利_欧美久久一级特黄毛片 | 成人一区视频_亚洲中文字幕久久精品蜜桃_91丨九色丨丰满人妖_一区二区三区免费在线看_中文字幕免费av_免费的黄色大片_黄色毛片a级片_亚洲国产成人精品无码区二本 | 成·人免费午夜视频_久草热这里有精品6_一二三四在线社区观看社区7_人摸人人人澡人人超碰手机版_www..99热_欧美又粗又大BBBBXXXX_日日操夜夜操天天爽_欧美诱惑一区 | 免费A级毛片高清视频哦哦_黑人巨茎美女高潮视频_日本精品一区二区三区在线播放_国产乱AⅤ一区二区三区_99av海角社区_剑来动漫高清在线观看_亚洲色图狠狠爱_成人淫片免费视频95视频 | 国产亚洲色欲色一色WWW_免费一级成人毛片_国产成人啪精品视频免费视频_在线观看无码AV网站永久免费_免费无码又爽又刺激高潮的视频_韩国免费视频_国产一区二区三区四区三区四_久久伊人精品波多野结衣 | 欧美劲爆婷婷五月久久_亚洲欧美自拍制服日韩一区_久久青草精品38国产_疯狂撞击丝袜人妻_福利一级片_日韩一区二区三区四区五区_最近2019年中文字幕_久久人人视频 | 在线视频青青草_久久精品天天中文字幕人妻_7777色鬼XXXX欧美色妇_国产98色在线_国产乱人伦偷精品视频免_中文字幕乱码亚洲精品一区_精品久久久久久中文字幕一区二区_国产一卡三卡四卡无卡精品 | 99精品偷拍视频一区二区三区_永久免费黄色_第一视角vk_日韩一级黄色大片_中文字幕高清视频_国产精品久久久久久久久绿色_婷婷久久久亚洲欧洲日产国码AV_国内精品久久久久精品 | 国产成人在线观看网站_久热RE这里精品视频在线6_鲁大师在线影院免费观看_狠狠综合亚洲综合亚洲色_久久中文字幕亚洲精品最新_亚洲欧美综合_亚洲AV无码日韩AV无码网站冲_特黄一级性片看 | 欧美人与动牲交免费观看_丝袜美女被遭强高潮网站_色欲天天天综合网_亚洲福利_久久三级影院_国产乱子伦在线观看免费_国产精品成人一区二区_久久久日韩精品一区二区 | 密色影院_成人国产精品久久久春色_国产a一区二区_久久免费看_美女光胸无遮挡18禁止观看_日韩在线一级片_欧美日韩精品欧美日韩精品一_成人欧美在线 | 一区二区观看_欧美性受xxxx黑人猛交88_精品国产91亚洲一区二区三区婷婷_成人在线观看免费网站_中文字幕久久熟女蜜桃_九色精品国产_久久人人爽人人爽人人片av高请_公天天吃我奶躁我的在线观看 | 亚洲黄色小说图片_国产精品久久久久久久综合_色一乱一伦一图一区二区精品_免费gogo少妇大尺寸视频_欧美成免费A级毛片_伊人色吧_性猛交xxxx免费看蜜桃_亚洲第一伊人 | 高级毛片_521av永久免费网_日韩国产欧美亚洲v片_欧美xxxav_麻豆精品A片免费观看_一级毛片免费毛片一级毛片免费_女人18毛片水最多_青草久久精品 | 成·人免费午夜视频_久草热这里有精品6_一二三四在线社区观看社区7_人摸人人人澡人人超碰手机版_www..99热_欧美又粗又大BBBBXXXX_日日操夜夜操天天爽_欧美诱惑一区 | 欧美人与动牲交免费观看网_99精品国产综合久久精品自在_伊人精品久久_日本熟妇乱人伦XXXX_日本视频在线看_xxxxx18国产_亚洲AV综合色区无码一二三区_久久久久成人片免费观看 | 国产亚洲精品久久久久久打不开_日本熟妇厨房XXXXX乱_99久久精品国产免费_国产综合13P_亚洲综合免费视频_99爱在线精品免费观看_中文字幕成熟丰满人妻_日本高清WWW午色夜在线视频 | 国产五月色婷婷六月丁香视频_永久av在线免费观看_秀人网妲己xiurenwang.cc_蜜桃av噜噜一区二区三_麻豆国产成人AV在线播放欲色_国产一区二区视频在线看_国产一级免费在线观看_麻豆成人精品国产免费 | 国产精品久久久久久99999_在线看片免费人成视频影院看_亚洲成人av片_久久久老熟女一区二区三区_AV激情亚洲男人的天堂_午夜小视频网站_免费av看_久久69精品久久久久久国产越南 | 极品美女扒开粉嫩小泬18P_日韩人妻无码中文字幕视频_九九色视频_日韩精品中文字幕视频_日韩精品人妻系列无码AV东京_久久国产精品无码一区二区三区_国产亚洲精品欧洲在线观看_无码毛片视频一区二区三区 | 久久久国产精品成人免费_日本丰满大乳免费xxxx_aaaa成人_亚洲色图自拍视频_真人性囗交视频_国产精品一区二区三区sss_FUCK东北老女人HD对话_91美女在线播放 | 吖v国产高清在线播放_国产尤物小视频在线观看_91九色婷婷_91杏吧在线观看_成人黄色片在线观看_屁屁影院ccyy备用地址_成人91av_99国产免费网址 | 免费在线观看av的网站_AV在线网址免费观看不卡_9色porny自拍视频一区二区_国产AV无码专区亚洲AV潘金链_亚洲永久av_综合久久国产_日本少妇毛茸茸高潮_亚洲色大成网站久久久 | 久久麻花精品一二三区_亚洲成人av网址_千百橹av入口在线观看_精品免费一区二区三区_中文字幕色一区二区_aaaaa爽爽爽久久久_国产精品美女久久久久久2022_成人黄色a视频 | 国内自拍中文字幕_国产在线va_狠狠婷婷_午夜看片在线观看_日本精品在线一区_特级做a爰片毛片免费看1o8_日韩一本之道一区中文字幕_老司机午夜永久免费影院 | 91九色视频在线_97人人爱_成人久草_色wwww全部免费_一级簧片免费看_91麻豆精品国产91久久久更新资源速度超快_国产98在线_欧美老妇与ZOZOZ0交 | 日韩中文字幕免费在线观看_国产欧美一级片_色网址在线观看_欧美一级大片免费看_chaopeng视频_a天堂在线观看视频_国产一精品av一免费爽爽_国产日产欧产精品 | 日产中文字幕在线观看_男人肌肌捅女人肌肌视频_99精品在线_四虎国产精品成人_在线一级成人_国产一区二区怡红院_欧美另类久久久精品_欧美顶级METART裸体全部自慰 | 国产99视频精品免费视频76_美女内射毛片在线看_亚洲不卡一区二区三区_欧美精品无码一区二区三区_国产在线观看不卡一区二区三区_青草视频免费在线观看_黑人强伦姧人妻久久_99视频免费 | 天天做爰天天爽_一二三区高清_久久精品国产一区二区三区不卡_免费无人区男男码卡二卡_年轻富婆私密推油到高潮_视频一区二区不卡_国产欧美呀洲一区二区_在线观看av永久免费 | 久久第一页_午夜网站视频_亚洲精品www_亚洲欧洲日产国码无码_成人亚洲A片V一区二区三区色欲_夜夜爱夜夜做夜夜爽_丰满又黄又爽少妇毛片_人人dvd | 欧美一级鲁丝片_亞洲中文字幕第一_www.亚洲精品.com_欧美色香蕉_91桃色免费观看_红杏国产成人精品视频_国产精品片www48888_精品国产精品三级精品av网址 | 欧美一级射_日本丰满熟妇有毛_99免费视频网站_一级片欧美日韩_国产19页_国产精品国产三级国产av品爱网_大二情侣宾馆啪实拍_深夜看国产毛片在线视频香蕉 | 国产香蕉一区二区三区_久久中文高清_中文字幕精品在线播放_在线免费看黄视频_国产午夜成人AV在线播放_成人福利在线观看视频_高清亚洲_免费超碰 | 私人影院在线观看视频_国产色视频网站免费_八戒八戒神马影院在线4_国产高清视频色拍_免费日本一区二区_天天做天天爱天天综合网2021_毛片av免费观看_99在线精品视频观看免费 | 国内xxxx乱子另类_4399伦理片_蜜乳av入口_我半夜摸妺妺的奶摸到高潮_亚洲精品偷拍影视在线观看_免费三级国产_亚洲VA在线∨A天堂VA欧美VA_中文字幕乱码亚洲影视 | 一夲道无码人妻精品一区二区_久久曰曰_51成人_成av在线_伊人久久情人综岁的合网18_国产日本一级二级三级_国产欧美一区二区精品仙草咪_欧美整片sss | 欧美bbbbwwbbbb视频_sese国产_亚洲第一福利在线观看_久久99成人_аⅴ中文天堂最新版在线_天堂VA视频一区二区_CHINESE性内射高清国产_a久久免费视频 国内自拍五区_被黑人的巨茎日出白浆_中文字幕第一区二区_国产亚洲美女精品久久久_亚洲porn_国产伦一区二区三区色一情_人人草人人人_久久无码字幕中文久久无码 | av天天av_欧美精品99_国产黄大片在线观看画质优化_国产资源免费观看_丝袜老师高潮呻吟高潮_日韩在线_亚洲kkk4444在线观看_亚洲大片69999 | 一级片国产_高清国产午夜精品久久久久久_hd国产人妖ts另类视频_欧美黑人精品一区二区不卡_午夜影院在线观看版_老司机亚洲精品影院_女明星黄网站色视频免费国产_国产网址 |