Unity3D中对协程和yield的理解

来源:互联网 发布:苹果音乐软件 itunes 编辑:程序博客网 时间:2024/04/30 09:09

        算起来接触unity也有将近两个月的时间了,刚开始的时候也接触到了协程,当时在官网上看到了一些列子,当时就感觉没什么特别的,但是并不知道他真正的意义是什么,以及在什么时候可以用。但是随着开发的深入,感觉有些东西弄不明白,总感觉心里不是滋味,现在就把我现在的理解和大家分享一下,一来呢,可以帮助和我一样的人,另外就是有什么错误的地方,还能得到大家的纠正,想想花费半个小时来写感觉也是值得。好了,开始干正事:

        关于协程的含义,我感觉还是有必要说一下。A coroutine is like a function that has the ability to pause execution and return control to Unity but then to continue where it left off on the following frame.这是官方对协程的描述,我在这里大概翻译一下:协程是一个具有停止执行当前函数和在下一帧中返回到当前执行的地方继续执行的函数。  有可能我翻译的不好,现在我给大家解释一下。先上一段代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TestCoroutine : MonoBehaviour {

public int count = 0;

// Use this for initialization
void Start () {
this.GetComponent<Button>().onClick.AddListener(OnClick);
}

// Update is called once per frame
void Update () {

}

IEnumerator GetMillions()
{
Debug.Log("开始测试协程:");
//现在协程就按照你指定的时间进行调用

//yield return new WaitForSeconds(5f);//#等待五分钟之后再调用
while(true)
{
count++;
yield return null;//每帧都会调用
Debug.Log("count 的值:" + count);
}
}

public void OnClick()
{
Debug.Log("开始条用协程");
StartCoroutine("GetMillions");
Debug.Log("协程调用结束");
}
}

如果你想看一下效果,在unity中创建一个button,然后创建一个TestCoroutine.cs的C#脚本,再给button按钮添加次脚本就可以了。


我在脚本中先定义了一个变量:count,这个是我用来测试yield 返回值的。先说一下协程是怎么调用的吧,协程调用很简单,我们定义一个IEnumerator 的函数,然后使用StartCoroutine(“”你用IEnumerator 定义的函数名“”),这样你就可以调用你的协程了。相信这些大家在看的时候都能明白,就是有些疑问,子执行的时候是什么样呢,协程是怎么停止当前执行的函数的,还有就是在下一帧时我的协程又是怎么调用的呢?现在说是怎么停止函数的,我们发现协程函数里面都会有一个yield return 语句,这个返回语句可以实现上面的功能,当我们使用 yield return new WaitForSeconds(5f);时,就可以让当前协程停止五秒钟,看你的需求,可以改里面的数字来修改停止的时间,使用yield break 就可以结束此协程,等时间到了,就会继续执行协程函数中下面的语句。现在我们应该明白怎么停止函数了,那怎么实现下一帧中返回到当前执行的地方继续执行的函数呢?其实很简单,我们使用yield return null;就可以了,因为协程是每帧都会执行一部分的,我们应该知道update()函数,每帧都会执行,协程函数也一样,每帧都会执行,并且是在update()函数之后执行,直到协程函数中的代码都执行完。当你执行代码的时候你就会看到这样的效果,我再协程函数里面加了一个while(true){}语句块,无限循环,这样协程函数就不会执行完,每帧都会去执行它了,每次都会对count进行加一的操作,并且会保留下来这个count这个值(这个是协程和多线程不一样的地方哦)。这个就是我目前对协程的理解,可能还会有更高级的用法,以后学习到了,我会继续写下来的。好了,来看一个我是用协程的例子吧,学以智勇吗,下面这个例子我就不详细说了,和这个基本差不多。

using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class LoadSceneProgressbar : MonoBehaviour {
public Slider progressBar;//进度条
public Text progressSliderText;//进度调显示进度的text
private AsyncOperation async;//异步加载场景的返回值
private int nowProcess;//当前进度
private string sceneName = "GameScene";//要跳转的场景的名字
// Use this for initialization
void Start()
{
StartCoroutine(LoadScene());
}

void Update()
{
if (async == null)
{
return;
}
int toProcess;
if (async.progress < 0.9f)
{
toProcess = (int)async.progress * 100;
}
else
{
toProcess = 100;
progressBar.value = 1;
}
if (nowProcess < toProcess)
{
nowProcess++;
}
progressBar.value = nowProcess / 100f;
progressSliderText.text = progressBar.value * 100 + "%";
if (nowProcess == 100)
{
async.allowSceneActivation = true;
}
}

IEnumerator LoadScene()
{
async = SceneManager.LoadSceneAsync(sceneName);
async.allowSceneActivation = false;
LoadManager.GetInstance().LoadPanel();
LoadManager.GetInstance().LoadText(Game.PathURL, "Data.txt");
LoadManager.GetInstance().LoadText(Game.PathURL, "DataSuduko.txt");
yield return async;
}
}

这个例子实现了一个加载场景时进度条的显示,相信大家也都会用到,嘿嘿。好了,没有介绍上面在unity中是怎么操作的,都是一些基本的操作,相信大家都会的。