热门标签 | 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








推荐阅读
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Navicat Premium 15 安装指南及数据库连接配置
    本文详细介绍 Navicat Premium 15 的安装步骤及其对多种数据库(如 MySQL 和 Oracle)的支持,帮助用户顺利完成软件的安装与激活。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • PyCharm下载与安装指南
    本文详细介绍如何从官方渠道下载并安装PyCharm集成开发环境(IDE),涵盖Windows、macOS和Linux系统,同时提供详细的安装步骤及配置建议。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 本文详细介绍了如何解决Uploadify插件在Internet Explorer(IE)9和10版本中遇到的点击失效及JQuery运行时错误问题。通过修改相关JavaScript代码,确保上传功能在不同浏览器环境中的一致性和稳定性。 ... [详细]
  • 本文介绍了如何利用JavaScript或jQuery来判断网页中的文本框是否处于焦点状态,以及如何检测鼠标是否悬停在指定的HTML元素上。 ... [详细]
  • 本文详细介绍了如何使用PHP检测AJAX请求,通过分析预定义服务器变量来判断请求是否来自XMLHttpRequest。此方法简单实用,适用于各种Web开发场景。 ... [详细]
  • 本文详细介绍了如何在BackTrack 5中配置和启动SSH服务,确保其正常运行,并通过Windows系统成功连接。涵盖了必要的密钥生成步骤及常见问题解决方法。 ... [详细]
  • This guide provides a comprehensive step-by-step approach to successfully installing the MongoDB PHP driver on XAMPP for macOS, ensuring a smooth and efficient setup process. ... [详细]
  • 探讨如何高效使用FastJSON进行JSON数据解析,特别是从复杂嵌套结构中提取特定字段值的方法。 ... [详细]
  • 导航栏样式练习:项目实例解析
    本文详细介绍了如何创建一个具有动态效果的导航栏,包括HTML、CSS和JavaScript代码的实现,并附有详细的说明和效果图。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • PHP 5.2.5 安装与配置指南
    本文详细介绍了 PHP 5.2.5 的安装和配置步骤,帮助开发者解决常见的环境配置问题,特别是上传图片时遇到的错误。通过本教程,您可以顺利搭建并优化 PHP 运行环境。 ... [详细]
  • GIMP 2.99.2 发布:UI 采用 GTK3 实现、原生支持高分屏和 Wayland
    开源项目评选最后一周,手里的5票再不用就没用了https:www.oschina.netprojecttop_cn_2020GIMP2.99.2已发布,同时这也标志着GIMP3.0的到来,其中最显著的变化是从GTK2过渡到GTK3工具包。基于 ... [详细]
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社区 版权所有