协程(五)简单模拟协程

作者: 86a262e62b0b | 来源:发表于2019-07-29 17:10 被阅读0次

    协程(一)基本使用
    协程(二)协程什么时候调用
    协程(三)IEnumerable、IEnumerator、foreach、迭代
    协程(四)yield与迭代器
    协程(五)简单模拟协程
    协程(六)有关优化

    参考:https://blog.csdn.net/here4one/article/details/83053417

    一.类似上一节的代码:

    IEnumerator TestCoroutine()
    {
        yield return null;              //返回内容为null
    
        yield return 1;                 //返回内容为1
    
        yield return "sss";             //返回内容为"sss"
    
        yield break;                    //跳出,类似普通函数中的return语句
    
        yield return 999;               //由于break语句,该内容无法返回
    }
    
    void Start()
    {
        IEnumerator e = TestCoroutine();
        while (e.MoveNext())
        {
            Debug.Log(e.Current);       //依次输出枚举接口返回的值
        }
    }
    

    二. 简单模拟协程

    1. 测试类
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Text : MonoBehaviour
    {
        public MyCoroutines myCoroutines;
        // Start is called before the first frame update
        void Start()
        {
            myCoroutines.MyStartCoroutine(h1());
            myCoroutines.MyStartCoroutine(h2());
        }
    
        private IEnumerator h1()
        {
            Debug.Log("h1 1");
            yield return null;
    
            Debug.Log("h1 2");
            yield return null;
    
            Debug.Log("h1 3");
            yield return new MyWaitForSeconds(2.0f);
    
            Debug.Log("h1 4");
            yield return null;
    
            Debug.Log("h1 5");
        }
    
        private IEnumerator h2()
        {
            Debug.Log("h2 1");
            yield return new MyWaitForSeconds(5.0f);
    
            Debug.Log("h2 2");
            yield return null;
    
            Debug.Log("h2 3");
            yield return null;
    
            Debug.Log("h2 4");
            yield return new MyWaitForSeconds(3.0f);
    
            Debug.Log("h2 5");
            yield return null;
        }
    }
    
    
    1. 协程类
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class MyCoroutines : MonoBehaviour
    {
        private List<IEnumerator> coroutines = new List<IEnumerator>();
        private bool isContinue;
    
        // 协程是在Update之后,LateUpdate之前执行,Unity未暴露出接口,只能将就着放在LateUpdate中
        private void LateUpdate()
        {
            if (coroutines.Count > 0)
            {
                for (int i = 0; i < coroutines.Count; i++)
                {
                    isContinue = true;
                    if (coroutines[i].Current is MyWaitForSeconds)
                    {
                        MyWaitForSeconds myWaitForSeconds = coroutines[i].Current as MyWaitForSeconds;
                        myWaitForSeconds.AddTime(Time.deltaTime);
                        if (!myWaitForSeconds.CheckTime())
                        {
                            isContinue = false;
                        }
                    }
    
                    if (isContinue && !coroutines[i].MoveNext())
                    {
                        coroutines.RemoveAt(i);
                        i--;
                    }
                }
            }
        }
    
        public void MyStartCoroutine(IEnumerator routine)
        {
            if (!coroutines.Contains(routine))
            {
                coroutines.Add(routine);
            }
        }
    }
    
    1. 延迟类
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class MyWaitForSeconds
    {
        private float delay;
        private float currentTime;
    
        public MyWaitForSeconds(float delay)
        {
            this.delay = delay;
            currentTime = 0f;
        }
    
        public void AddTime(float addTime)
        {
            currentTime += addTime;
        }
        public bool CheckTime()
        {
            if (currentTime >= delay)
            {
                return true;
            }
            return false;
        }
    }
    
    1. 测试结果


      测试结果
    1. 另外在放上一个协程的交叉调用类
    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;  
                }  
                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);  
            }  
        } 
    }  
    

    相关文章

      网友评论

        本文标题:协程(五)简单模拟协程

        本文链接:https://www.haomeiwen.com/subject/tmhbrctx.html