自己实现unity的协程调度器--利用c#迭代器和unity生命周期函数

通过unity协程调度器来开启协程,yield return后面逻辑的执行时机如下
yield return不同内容的含义
1.下一帧执行
yield return 数字;
yield return null;
//在update和LateUpdate之间执行

2.等待指定秒过后执行
Yield return new WaitforSecends(秒):
//在update和LateUpdate之间执行

3.等待下一个固定物理帧更新时执行
Yeild return WaitForFixedUpdate();
//在FixedUpdate和碰撞相关函数之后执行

4.等待摄像机和GUI渲染过后执行
Yield return new WaitForEndOfFrame();
//在LateUpdate之后的渲染相关处理完毕后
主要用于做截图功能时

5.一些特殊类型的对象,比如异步加载相关函数返回的对象
//一般在Update和LateUpdate之间执行

6.跳出协程
Yield return;

此时我利用c#迭代器和unity生命周期函数来实现自己的协程调度器,让yield return 数字,表示等待多少秒执行后面的逻辑。也就是实现 new WaitforSecends(秒)类的功能。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class YiedlReturnTime
{
    //记录 下次还要执行的 迭代器接口
    public IEnumerator e;
    //记录 下次执行的时间
    public float time;
}

public class CoroutineMrg : MonoBehaviour
{
    //单例模式
    private static CoroutineMrg instance;
    public static CoroutineMrg Instance => instance;
    //存储迭代器函数对象的容器  
    //因为可以在不同的地方通过该协程调度器来开启协程(同时可以开启多个协程)
    private List<YiedlReturnTime> list = new List<YiedlReturnTime>();

    void Start()
    {
        instance = this;
    }

    void Update()
    {
        //为了避免在循环的过程移除元素而导致元素位置改变,需要从列表中移除内容 我们可以倒着遍历
        for(int i=list.Count-1;i>=0;i--)
        {
            //判断 当前迭代器函数 是否到了下一次执行的时间
            if(list[i].time<=Time.time)
            {
                if(list[i].e.MoveNext())
                {
                    //如果是true 那还需要对该迭代器 进行处理
                    if(list[i].e.Current is int)
                    {
                        list[i].time = Time.time + (int)list[i].e.Current;
                    }
                    else
                    {
                        //该list 只是存储 处理时间相关 等待逻辑的  迭代器函数
                        //如果是别的类型就因该存储到别的容器中
                    }    
                }
                else
                {
                    //后面已经没有可以等待和执行的了 证明已经执行完毕了逻辑。
                    list.RemoveAt(i);
                }
            }
        }
    }
    public void MystartCoroutine(IEnumerator e)
    {
        //传入一个 迭代器函数返回的结构,那么一来就因该执行它
        //一来就执行第一步
        if(e.MoveNext())
        {
            //如果yield return 返回的是数字
            if(e.Current is int)
            {
                //按思路 应该把 这个迭代器函数 和它下一次执行的时间点 记录下来
                //然后不停检测 时间 是否达到了 下一次执行的时间点
                YiedlReturnTime y = new YiedlReturnTime();
                y.e = e;
                y.time = Time.time + (int)e.Current;
                //把记录的信息记录到数据容器中
                list.Add(y);
            }
            else
            {
                //其它类型代表的意思 需要自行实现
            }
            
        }
    }
}


测试类

using System.Collections;
using UnityEngine;

public class Lession15 : MonoBehaviour
{
    IEnumerator MyCoroutine()
    {
        print("第1次");
        yield return 1;//等待1秒
        print("第2次");
        yield return 10;//等待10秒
        print("第3次");
    }
   
    void Start()
    {
        //利用自己实现的协程调度器 来 开启协程
        CoroutineMrg.Instance.MystartCoroutine(MyCoroutine()); 
    }

}

注意:两个类都要挂载到游戏物体上,查看截图时间,分别等待了1秒和10秒。
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值