控制Coroutine的节奏

http://unitygems.com/advanced-coroutines/ 里展示了一个在两个Coroutine间切换的Demo。

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using System.Collections;

[RequireComponent(typeof(GUIText))]
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());
     //     _current = _countUp;
     }
    
     void Update()
     {
          //Show the current value on the screen
          guiText.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()
     {
          Debug.Log("Test()");
          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;    //should write like this, or yield return new WaitForSeconds(0.5f) in CountDown() has no effect.
               }
               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.5f);
          }
     }   
}

需要注意到,上述代码中,
  IEnumerator DoHijack()
     {
          Debug.Log("Test()");
          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;    //should write like this, or yield return new WaitForSeconds(0.5f) in CountDown() has no effect.
               }
               else
                    //Otherwise wait for the next frame
                    yield return null;
          }
     }
中间的yield return _current.Current;这一行要是换为了yield return null;或者yield return 2等任意不需要耗时计算的东东,CountDown()里的WiatForSeconds就会没有效果。  这是因为DoHijack和CountDown()是两个不同的Coroutine,虽然是在DoHijack()里调用的CountDown(),但两者相互独立,DoHijack不用等待CountDown(),除非在代码里被要求这么干。
CoroutineA遇到yield就马上返回了,Unity就可以去执行其他的Coroutine,只是在再次进入CoroutineA时,需要检测上次那个yield语句的内容是否已经满足。其他Coroutine等待CoroutineA.Current时也需要等待CoroutineA的那个yield语句的内容是否已经满足。


于是在http://blog.csdn.net/u010153703/article/details/38557237 里,我们的Fibonacci数列若想看到数字缓慢地出现,可以修改如下:

using UnityEngine;
using System.Collections;
using System;

public class Fibonacci : MonoBehaviour {

     //int Fk = 0;

     IEnumerator Fib()
     {
          int Fkm2 = 1;
          int Fkm1 = 1;
          yield return 1;
          yield return 1;
          while (Fkm2 + Fkm1 < int.MaxValue)
          {
               int Fk = Fkm2 + Fkm1;
               Fkm2 = Fkm1;
               Fkm1 = Fk;
                  yield return new WaitForSeconds(0.5f);
               yield return Fk;
          }
     }

     IEnumerator ShowFib()
     {
          IEnumerator fib = Fib ();
     //     StartCoroutine(fib);  //should not be written here if you want to use MoveNext() which meaning RunCoroutine yourself

          for (int i=0; i<20; ++i)
          {
               if (!fib.MoveNext())
                    break;

               Debug.Log(fib.Current);
               yield return fib.Current;
          }
          yield return null;
     }

     // Use this for initialization
     void Start () {
          StartCoroutine(ShowFib());
          //ShowFib();
     
     }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值