Unity3D之协程

  Unity3D提供了一个工具叫做“协程”,所谓协程就是使用StartCoroutine()里面添加一个方法来调用该方法。对这个被调用的方法有如下规定:返回值必须是IEnumerator类型。那么为什么要使用协程呢?通常这是为了应付某一类需要,比如想要延时执行某一段代码,或者使用www进行一些请求和加载等阻塞操作。

  协程与多线程没有关系。协程每一帧都执行,时间段位于LateUpdate之后。所以说它只不过是在主线程里面每帧执行的一个函数而已。协程使用的原理类似于foreach循环,都是使用迭代器来实现,因此它也包括IEnumerator接口的Current属性和MoveNext()方法。这两个东东都是迭代器比较重要的内容。

  MSDN上对Current的解释为:Gets the current element in the collection,对MoveNext()的解释为:Advances the enumerator to the next element fo collection。从这两个解释可以看出来,Current返回的是集合当前的元素,MoveNext()推动循环向下一个元素。MoveNext()的返回值是bool,当返回true时,就向下走一级,返回false,则停止。假如循环到最后一个元素,肯定返回false。

  对于协程来说,当进行至yield return语句时,检查yield return后面的条件是否满足,如果满足,则执行后面的代码。如果不满足,则记录下该位置,下一帧继续检查,直到满足为止。这里体现了协程的主要作用了,假如你用www下载一个数据,你肯定想知道什么时候下载完。只有下载完了yield return www的下一行才会得到执行。

  下边看一个测试类,此类来自网络,通过一个协程内的循环来交替执行另外两个协程。注意,这些协程都是在主线程里面,可以随意访问Unity3D的对象和组件。

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());
    }

    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()
    {
        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;
                if(_current.Current!=null)
                Debug.Log(_current.Current.ToString());//wait for seconds OR null

            }
            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);
        }
    }

}

  现在简单解释下该类。首先定义了三个IEnumerator接口类型的变量用来接受协程的返回值,在Start方法里面调用其中一个DoHijack()协程。这个协程里面有一个无限循环,在该循环里面检查_current是否赋值了,如果有值就调用该IEnumerator接口里面的MoveNext()方法,相当于每次循环都执行一遍_current对应的方法。至于_current.Current则返回了两个协程CountUp和CountDown的返回值,输出一下得到值为Null或WaitForSeconds(),恰恰是yield return后跟的返回值。

时间: 2024-10-12 21:58:03

Unity3D之协程的相关文章

Unity3d之协程自实现测试

using UnityEngine; using System.Collections; public class TestStartCoroutine : MonoBehaviour { IEnumerator m_etor; bool m_moveNext; MyWaitForSeconds m_waiter; #region MyRegion class MyWaitForSeconds { int m_seconds; float m_timer; public MyWaitForSec

unity3D中协程和线程混合

这是我google unity3D一个问题偶然发现的在stackflow上非常有趣的帖子: 大意是 要在unity3D上从server下载一个zip,并解压到持久化地址.并将其载入到内存中.以下展示了这样的使用方法: IEnumerator LongCoroutine() { yield return StartCoroutine(DownloadZip()); ExtractZip(); yield return StartCoroutine(LoadZipContent()); } 可是Ex

【Unity3D基础教程】(五):详解Unity3D中的协程(Coroutine)

[狗刨学习网] 为什么需要协程 在游戏中有许多过程(Process)需要花费多个逻辑帧去计算. 你会遇到"密集"的流程,比如说寻路,寻路计算量非常大,所以我们通常会把它分割到不同的逻辑帧去进行计算,以免影响游戏的帧率. 你会遇到"稀疏"的流程,比如说游戏中的触发器,这种触发器大多数时候什么也不做,但是一旦被调用会做非常重要的事情(比图说游戏中自动开启的门就是在门前放了一个Empty Object作为trigger,人到门前就会触发事件). 不管什么时候,如果你想创建

Unity3D 协程 Coroutine

协程(Coroutine)的概念存在于很多编程语言,例如Lua.ruby等.而由于Unity3D是单线程的,因此它同样实现了协程机制来实现一些类似于多线程的功能,但是要明确一点协程不是进程或线程,其执行过程更类似于子例程,或者说不带返回值的函数调用. 协程类型IEnumerator 在内部方法使用 yield return 语句,直观的说语句说在位置便是协程暂停,并且将控制权移交给Unity引擎以及之后继续执行余下逻辑的地方. 例如 IEnumerator Method(){ int i=0;

Unity3D 协程 浅谈

协程 理解:协程不是线程,也不是异步执行(知道就行). 1.协程和MonoBehaviour的Update函数一样,也是在MainThread中执行的(一定得明白这句话意思). void Start () { StartCoroutine(HelloCoroutine()); } void Update () { Debug.Log("Update..."); } void LateUpdate() { Debug.Log("LateUpdate..."); } I

Unity3D协程介绍 以及 使用

作者ChevyRay ,2013年9月28日,snaker7译  原文地址:http://unitypatterns.com/introduction-to-coroutines/ 在Unity中,协程(Coroutines)的形式是我最喜欢的功能之一,几乎在所有的项目中,我都会使用它来控制运动,序列,以及对象的行为.在这个教程中,我将会说明协程是如何工作的,并且会附上一些例子来介绍它的用法. 协程介绍 Unity的协程系统是基于C#的一个简单而强大的接口 ,IEnumerator,它允许你为自

yield学习续:yield return迭代块在Unity3D中的应用——协程

必读好文推荐: Unity协程(Coroutine)原理深入剖析 Unity协程(Coroutine)原理深入剖析再续 上面的文章说得太透彻,所以这里就记一下自己的学习笔记了. 首先要说明的是,协程并不是线程,协程是运行在主线程中的,是和主线程同步执行的代码,不同的地方是运行的方法可以被yield return在当前帧进行打断,到下一帧后可以继续从被打断的地方继续运行. 下面我们看一个示例,场景中有一个空的GameObject对象,其绑定了下面的脚本: 1 using UnityEngine;

Unity3D停止不了协程

我直接用StopCoroutine直接像StartCoroutine一样里面加方法不能停止该协程.通过把协程赋予到变量再控制此变量来停止才能中断此协程. private IEnumerator cortinue; cortinue = E_MoveToPoint(); private IEnumerator E_MoveToPoint() { } StopCoroutine(cortinue); 原文地址:https://www.cnblogs.com/weiqiangwaideshijie/p

Unity协程(Coroutine)管理类——TaskManager工具分享(转)

尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 在分享vp_Timer 中提到,没有继承的MonoBehaviour,没有Update,InVoke 和StartCoroutine的机制,vp_Timer就是提供了InVoke的机制,而且还可以统一管理.本篇D.S.Qiu要分享的TaskManager就是一个协程 管理类. TaskManager —— Unity3D Managed Coroutines with Start, Stop, Resume ,看