1. 程式人生 > >unity中協程的理解和學習

unity中協程的理解和學習

先放二篇大神寫的部落格,很受用。謝謝https://blog.csdn.net/huang9012/article/details/38492937

http://www.unity.5helpyou.com/2658.html

今天在看Unity中協程的作用先放一個物體漸隱漸現的效果吧

public class Test : MonoBehaviour 
{

    void Start()
    {
        StartCoroutine(Test1());
    }

    IEnumerator Test1()
    {
        while (true)
        {
            //獲得物體上的Alpha值
            float a = gameObject.GetComponent<Renderer>().material.color.a;
           //使用for迴圈讓Appha值從1減到0 一開始我以為這裡面的兩個for迴圈會同時的執行但是我執行後發現是按順序執行的執行完第一個才能執行下一個
          想想也是每一次到Yield程式碼就會被暫停,執行LateUpdate後,再次重新回到Update中執行完後再次重執行協程,這是我這個小白的理解,希望大神可以給我指出不對的地方
            for (float i = 1; i >= 0; i -= Time.deltaTime*0.3f)
            {
                //每變化一次就暫停一次,等下一次繼續執行
                gameObject.GetComponent<Renderer>().material.color = new Color(0, 0, 1, i);
                Debug.Log("A********" + a);
                yield return 0;
                Debug.Log("I********"+i);
            }
            yield return new WaitForSeconds(1);//目的變到透明後暫停1秒在慢慢變回來
            //再讓Alpha的值從0慢慢變化到1
            for (float i = 0; i <= 1; i += Time.deltaTime*0.3f)
            {
                gameObject.GetComponent<Renderer>().material.color = new Color(0, 0, 1, i);
                yield return 0;
                Debug.Log("A********" + i);
            } 
        }
        yield return 0;
    }


    void Update()
    {
        Debug.Log("執行Update函式");
    }

    void LateUpdate()
    {
        Debug.Log("執行LateUpdatee函式");
    }

}
void Start ()
    {
        Debug.Log("Start函式裡協程執行之前的語句1"); //先執行這一句
        StartCoroutine(Do());                      //然後開啟一個協程,輔助程式執行
        Debug.Log("Start函式裡協程執行之後的語句4"); //接著向下執行,協程不會影響主執行緒的執行
    }

   // 第一部分學習
    IEnumerator Do()
    {
            Debug.Log("Do協程暫停之前的語句2"); //協程裡面首先執行這一句 2 4語句的誰先後執行與機器的CPU有關
            yield return 0;                   //暫停下一幀在執行後面的語句
            Debug.Log("Do協程暫停之後執行的語句6");
    }

然後我們可以看到執行的順序 ,這裡面Update裡面的方法正常執行不會影響到,也就是每一幀都會呼叫。

void Start ()
    {
        Debug.Log("Start函式裡協程執行之前的語句1");  //1首先執行這一條語句
        StartCoroutine(Do());                       //2開啟協程調到Do協程裡
        Debug.Log("Start函式裡協程執行之後的語句4");  //不受協程影響正常執行
    }

   // 第一部分學習
    IEnumerator Do()
    {
            Debug.Log("Do協程暫停之前的語句2");      //3執行這一條語句
            yield return StartCoroutine(NewDo());  //4呼叫下一個協程
            Debug.Log("Do協程暫停之後執行的語句6");  //8.NewDo執行完畢執行這一條語句
    }

    IEnumerator NewDo()
    {
        Debug.Log("NewDo暫停之前的語句3");          //5執行這一條語句
        yield return new WaitForSeconds(2);        //6暫停執行返回Do中,Do中產生中斷指令暫停返回Start中
        Debug.Log("NewDo暫停之後執行的語句5");      //7 2秒後,NewDo的中斷指令完成並繼續執行
    }

 

void Start ()
    {
        Debug.Log("Start函式裡協程執行之前的語句1");
        StartCoroutine(SayHelloFive());          //我們可以控制呼叫次數
        //StartCoroutine(SayHelloEveryFrame());  //相當於Update
        Debug.Log("Start函式裡協程執行之後的語句4");
    }

  IEnumerator SayHelloFive()
    {
        for (int i = 0; i < 5; i++)
        {
            Debug.Log("Hello");
            yield return 0;
        }
    }

    IEnumerator SayHelloEveryFrame()
    {
        while (true)
        {
            Debug.Log("Hello");
            yield return 0;
        }
    }

做一個簡單的計時器 

 IEnumerator Seconds()
    {
        int second = 0;
        while (true)
        {
            for (float i = 0; i <= 1; i += Time.deltaTime)
            {
                yield return 0;
            }
            second++;
            Debug.Log(second + "&&&&&&&&&&&");
        }
    }

開啟協程和關閉協程

StartCoroutine(Seconds());
StartCoroutine(SayHelloEveryFrame());
//如果用這種方式開啟協程,不能關閉指定的協程,只能 StopAllCoroutines();關閉全部

//如果想要關閉其中一個我們需要在開啟的時候就用字串的方式
  StartCoroutine("Seconds");
  StopCoroutine("Seconds"); //有引數寫在後面就可以
    IEnumerator RepeatMessage(int count,float frequecy,string message)  //執行的次數,頻率,執行時顯示的內容
    {
        for (int i = 0; i < count; i++)
        {
            Debug.Log(message);
            for (float timer = 0; timer < frequecy; timer+=Time.deltaTime)
            {
                yield return 0;
            }
        }
    }//效果就是每隔我們設定的頻率就列印輸出一次資訊

 協程的巢狀

    IEnumerator SaySomeThings()
    {
        Debug.Log("開始協程");
        yield return StartCoroutine(Wait(1));
        Debug.Log("1秒後收到的資訊");
        yield return StartCoroutine(Wait(2.5f));
        Debug.Log("2.5秒後收到的資訊");
    }

    IEnumerator Wait(float duration)
    {
        for (float timer = 0; timer < duration; timer+=Time.deltaTime)
        {
            yield return 0;
        }
    }

 

一般協程裡的內容實在Update之後LateUpdate之前執行的,這是我看別人說的我也測試了也是這樣的,如果有不對的地方

還希望前輩們可以給我指出。

學習一樣東西首先要明白1、它的用處是什麼2、在哪些方面會被用到3、使用的方法.還希望可以給我知道一下謝謝

1:小白自己的看法是協程可以用來執行不是在一幀執行完的功能,像計時器和一些漸變。

2:在計時器和做非同步載入、控制遊戲物件(這個還不太明白,希望有大神可以指導一下)

  • l 在程式中呼叫StopCoroutine()方法只能終止以字串形式啟動(開始)的協程;
  • l 多個協程可以同時執行,它們會根據各自的啟動順序來更新;
  • l 協程可以巢狀任意多層;
  • l 如果你想讓多個指令碼訪問一個協程,那麼你可以定義靜態的協程;
  • l 協程不是多執行緒(儘管它們看上去是這樣的),它們執行在同一執行緒中,跟普通的指令碼一樣;
  • l 如果你的程式需要進行大量的計算,那麼可以考慮在一個隨時間進行的協程中處理它們;
  • l IEnumerator型別的方法不能帶ref或者out型的引數,但可以帶被傳遞的引用;
  • l 目前在Unity中沒有簡便的方法來檢測作用於物件的協程數量以及具體是哪些協程作用在物件上。

以上是小白我自己的總結,有不對的地方還希望大家指出,謝謝大家的指教