热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

Unity协程&在编辑器中使用协程

尊重原创,转载请在文首注明出处:http:blog.csdn.netcai612781articledetails78992805一,定义Unity协程(Corout

尊重原创,转载请在文首注明出处:http://blog.csdn.net/cai612781/article/details/78992805

一,定义

Unity协程(Coroutine),不是卖机票的携程,是一种类似子线程的机制,可以用来实现一些延时处理的需求,c#中通过yield return语句配合可以中断执行,延时一定时间后从中断处继续执行。


二,注意

协程不是线程,协程不是线程,协程不是线程,协程还是在主线程里!!!


三,语法

脚本需要继承MonoBehaviour,提供了两个方法StartCoroutine(IEnumerator routine)或者StartCoroutine(string methodName)开启一个协程,以及对应的StopCoroutine(IEnumerator routine)或StopCoroutine(string methodName)关闭协程。推荐使用前者,因为传递方法名需要用到反射机制,影响性能。


四,常见应用

1)延时(别想歪)

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour
{
	IEnumerator Start()
	{
		Debug.Log("Start--" + Time.time);
		yield return StartCoroutine(WaitAndLog);
		Debug.Log("End--" + Time.time);
	}
	
	IEnumerator WaitAndLog()
	{
		yield return new WaitForSeconds(3);
		Debug.Log("Wait--" + Time.time);
	}
}
2)分帧加载

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour
{
	private int _num,_total;
	Start()
	{
		StartCoroutine(LoadAssets);
	}
	
	IEnumerator LoadAssets()
	{
		while(_num <_total)
		{
			_num++;
			Debug.Log("Load an Asset");
			yield return null;
		}
	}
}


五,yield

yield语句用于暂停协程的执行,yield return 的值决定什么时候恢复协程的执行。yield return 返回一个IEnumerator对象,当该对象的MoveNext()返回false,即该对象的Current已迭代到最后一个元素时,才会执行yield return后的代码。

yield语句的返回有如下类型:
yield return null;//下一帧再继续往下执行
yield return new WaitForFixedUpdate();//等到下一次调用FixedUpdate再往下执行
yield return new WaitForSceonds(n);//等待n秒再往下执行
yield return StartCoroutine(Method);//开启另一个协程,直到Method执行完毕再往下执行
yield return new WaitForEndOfFrame();//等到该帧结束再往下执行
yield return WWW;//等待资源加载完成再往下执行
yield break;//结束协程

六,执行顺序

协程是每帧lateUpdate前执行yield return之前的代码,lateUpdate后执行yield return之后的代码。
不同yield return返回值的执行顺序,通过官方文档的一张流程图可以清晰地了解:
http://docs.unity3d.com/uploads/Main/monobehaviour_flowchart.svg

七,原理

Unity的协程应该是一个扩展成支持嵌套的迭代器(IEnumator)。
它将c# IEnumerator封装为Coroutine对象,它记录了该协程的上一级协程是谁,当这个协程执行完成,会继续执行上一级协程。
当Unity Coroutine调用IEnumerator的MoveNext返回一个新Coroutine时,Unity设置新对象的上级Coroutine为当前Coroutine,同时将新Coroutine压入队列,通过此实现嵌套。
然后Unity在主线程中定时检测当前每个等待的Coroutine,满足条件则执行。

八,在Editor下使用Coroutine

编辑器下因为没有运行Unity,也没有创建GameObject,因此也无法通过Monobehaviour的StartCoroutine创建协程。
以下代码来自网上不知哪位大牛,根据Unity协程原理另外实现了个协程:
1,EditorCoroutine协程类实现了IEnumerator接口,在MoveNext函数中实现了嵌套调用协程
public class EditorCoroutine : IEnumerator  
    {  
        private Stack executionStack;  
  
        public EditorCoroutine(IEnumerator iterator)  
        {  
            this.executiOnStack= new Stack();  
            this.executionStack.Push(iterator);  
        }  
  
        public bool MoveNext()  
        {  
            IEnumerator i = this.executionStack.Peek();  
  
            if (i.MoveNext())  
            {  
                object result = i.Current;  
                if (result != null && result is IEnumerator)  
                {  
                    this.executionStack.Push((IEnumerator)result);  
                }  
  
                return true;  
            }  
            else  
            {  
                if (this.executionStack.Count > 1)  
                {  
                    this.executionStack.Pop();  
                    return true;  
                }  
            }  
  
            return false;  
        }  
  
        public void Reset()  
        {  
            throw new System.NotSupportedException("This Operation Is Not Supported.");  
        }  
  
        public object Current  
        {  
            get { return this.executionStack.Peek().Current; }  
        }  
  
        public bool Find(IEnumerator iterator)  
        {  
            return this.executionStack.Contains(iterator);  
        }  
    }  
2,EditorCoroutineRunner类,类似MonoBehaviour,提供了StartEditorCoroutine方法创建一个协程
public static class EditorCoroutineRunner  
{      
    private static List editorCoroutineList;  
    private static List buffer;  
  
    public static IEnumerator StartEditorCoroutine(IEnumerator iterator)  
    {  
        if (editorCoroutineList == null)  
        {  
            editorCoroutineList = new List();  
        }  
        if (buffer == null)  
        {  
            buffer = new List();  
        }  
        if (editorCoroutineList.Count == 0)  
        {  
            EditorApplication.update += Update;  
        }  
  
        buffer.Add(iterator);  
      
        return iterator;  
    }  
  
    private static bool Find(IEnumerator iterator)  
    {   
        foreach (EditorCoroutine editorCoroutine in editorCoroutineList)  
        {  
            if (editorCoroutine.Find(iterator))  
            {  
                return true;  
            }  
        }  
  
        return false;  
    }  
  
    private static void Update()  
    {  
        editorCoroutineList.RemoveAll  
        (  
            coroutine => { return coroutine.MoveNext() == false; }  
        );  
  

        if (buffer.Count > 0)  
        {  
            foreach (IEnumerator iterator in buffer)  
            {  
                if (!Find(iterator))  
                {  
                    editorCoroutineList.Add(new EditorCoroutine(iterator));  
                }  
            }  
  
            buffer.Clear();  
        }  
  
        if (editorCoroutineList.Count == 0)  
        {  
            EditorApplication.update -= Update;  
        }  
    }  
}  
3,调用
using UnityEngine;
using System.Collections;

public class ExampleClass
{
	Start()
	{
		EditorCoroutineRunner.StartEditorCoroutine(Routine);
	}
	
	IEnumerator Routine()
	{
		Debug.Log("Routine");
		yield return null;
	}
}

九,参考

http://gad.qq.com/article/detail/10552
http://blog.csdn.net/langresser_king/article/details/44244369








推荐阅读
  • 推荐一个ASP的内容管理框架(ASP Nuke)的优势和适用场景
    本文推荐了一个ASP的内容管理框架ASP Nuke,并介绍了其主要功能和特点。ASP Nuke支持文章新闻管理、投票、论坛等主要内容,并可以自定义模块。最新版本为0.8,虽然目前仍处于Alpha状态,但作者表示会继续更新完善。文章还分析了使用ASP的原因,包括ASP相对较小、易于部署和较简单等优势,适用于建立门户、网站的组织和小公司等场景。 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 如何去除Win7快捷方式的箭头
    本文介绍了如何去除Win7快捷方式的箭头的方法,通过生成一个透明的ico图标并将其命名为Empty.ico,将图标复制到windows目录下,并导入注册表,即可去除箭头。这样做可以改善默认快捷方式的外观,提升桌面整洁度。 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文是一位90后程序员分享的职业发展经验,从年薪3w到30w的薪资增长过程。文章回顾了自己的青春时光,包括与朋友一起玩DOTA的回忆,并附上了一段纪念DOTA青春的视频链接。作者还提到了一些与程序员相关的名词和团队,如Pis、蛛丝马迹、B神、LGD、EHOME等。通过分享自己的经验,作者希望能够给其他程序员提供一些职业发展的思路和启示。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • Pycharm编辑器取消双击shift弹出搜索框的方法
    在使用Pycharm编辑器时,双击shift会弹出搜索框界面,导致输入失去焦点,给用户带来不便。本文介绍了取消双击shift弹出搜索框的方法:在Pycharm中双击shift,输入registry并回车,找到“ide.suppress.double.click.handler”并勾选后,关闭即可解决该问题。通过这个方法,你再也不会被shift问题困扰了。 ... [详细]
author-avatar
我是曰照人_692
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有