C#中Coroutine的深层研究

最近用Coroutine协同程序取代Update的人越来越多,故此我对Coroutine进行了一些研究,以进一步了解该函数的作用,好加快往后游戏的开发效率。

这段文章主要是对拥有一定Coroutine只是的朋友们,若还不了解Coroutine的话可以先去看看Unity3D的文档,再过来做进一步的深层了解。

首先先贴上一段代码:

public class ResearchCoroutine : MonoBehaviour 
{
	void Start ()
	{
		StartCoroutine ( CheckInputPartOne () ) ;	
	}
	
	IEnumerator CheckInputPartOne ()
	{
		Debug.Log ( "Part One Start" ) ;
		bool SwitchOffTheLoop = false ;
		while ( !SwitchOffTheLoop )	
		{
			if ( Input.GetButtonDown ( KeyCode.Space ) )
			{
				yield return StartCoroutine ( CheckInputPartTwo () ) ;
				SwitchOffTheLoop = true ;
			}
			yield return null ;
		}
		Debug.Log ( "Part One End" ) ;
	}
	
	IEnumerator CheckInputPartTwo ()
	{
		Debug.Log ( "Part Two Start" ) ;
		bool SwitchOffTheLoop = false ;
		while ( !SwitchOffTheLoop )
		{
			if ( Input.GetButtonUp ( KeyCode.Space ) )	
			{
				SwitchOffTheLoop = true ;
			}
			yield return null ;
		}
		Debug.Log ( "Part Two End" ) ;
	}
}

很简单的一段代码,主要是当CheckInputPartOne的协同程序运行的时候,当我按下空格键,则该协同程序就会被挂起,并开始运行CheckInputPartTwo,直到我放开空格键,输出如下:

C#中Coroutine的深层研究_第1张图片

不出所料,在CheckInputPartOne挂起了之后,则会直到CheckInputPartTwo结束运行后才会继续运行接下来的字段。

那么接下来我就要稍微为协同程序辟谣一下,曾经看过多个关于协同程序的博文都会对yield return 做出如此解释:

yield return null 表示在1帧后继续以下字段,yield return 2 则为2帧。

这不是真实的,首先我们来看这段实验:

我们在上面的代码中增加一个浮点数变量以用来记载CheckInputPartTwo在yield return 前后间隔的时间差,具体代码如下:

public class ResearchCoroutine : MonoBehaviour 
{
	private float Timer ;
	void Start ()
	{
		StartCoroutine ( CheckInputPartOne () ) ;	
	}
	
	IEnumerator CheckInputPartOne ()
	{
		Debug.Log ( "Part One Start" ) ;
		bool SwitchOffTheLoop = false ;
		while ( !SwitchOffTheLoop )	
		{
			if ( Input.GetKeyDown ( KeyCode.Space ) )
			{
				Timer = Time.time ;
				Debug.Log ( "Set Timer" ) ;
				yield return StartCoroutine ( CheckInputPartTwo () ) ;
				SwitchOffTheLoop = true ;
			}
			yield return null ;
		}
		Debug.Log ( "Part One End" ) ;
	}
	
	IEnumerator CheckInputPartTwo ()
	{
		Debug.Log ( "Part Two Start" ) ;
		bool SwitchOffTheLoop = false ;
		while ( !SwitchOffTheLoop )
		{
			if ( Input.GetKeyUp ( KeyCode.Space ) )	
			{
				SwitchOffTheLoop = true ;
			}
			yield return null ;
		}
		Timer = Time.time - Timer ;
		Debug.Log ( "Time Used: " + Timer ) ;
		Debug.Log ( "Part Two End" ) ;
	}
}
输出如下:

C#中Coroutine的深层研究_第2张图片
接下来我们将CheckInputPartTwo的 yield return null 改为 yield return 1000,如果说yield return null 是在1帧后返回接下来的字段,那么yield return 1000是不是在1000帧以后返回接下来的字段?我们来看看结果如何:

C#中Coroutine的深层研究_第3张图片

结果是,所需时间完全一样。其实很简单,yield return 只是为我们执行了IEnumerator的moveNext函数,而后面的值只是因为IEnumerator需要一个IEnumerable作为一个返回值,而IEnumerable其实就是获取一个IEnumerator,因此我们返回yield return 后面的数字或者任何参数其实就是相当于创建并返回了一个IEnumerator,因此无论你设的数字多么的大,上一段与下一段的时间差也永远只是1帧,除非你使用WaitForSeconds,要不然时间差永远都不会有任何改变。


由于我仍然是个还在学习的人,如果有不对还欢迎指出


你可能感兴趣的:(Unity3D)