Unity协程队列,顺序分帧处理

游戏开发过程中经常会遇到要加载一片场景资源的情况,先不考虑如何加载的情况,对于一大片场景的加载和显示,如果在一帧内完成的话,对性能会有很大的小号,造成瞬间帧率下降,产生性能峰值。
一般这种不需要实时性的加载都会分帧处理,把压力平摊下去,为了使加载过程更加平滑与受控,博主写一个协程队列去控制我们加载过程中协程的调用顺序与次数,更好的平滑我们的加载过程。
因为这里协程的调用是使用迭代器的 MoveNext,并非调用StartCoroutine开启动迭代器,所以无法实现计时器的功能(WaitForSeconds), 仅支持yield return null,能够满足此条件的才能使用该脚本, 同时这种实现方法也带来性能优势,减少每次调用一次StartCoroutine都会带来24B的内存消耗,若开启协程很平凡,这个消耗还是很明显的。
使用方法是找个GameObject挂载CoroutineManager脚本,需要管理的协程通过CoroutineManager.EnqueueWork方法加到协程队列,下面源码中也有测试代码。



协程队列处理:
EnqueueWork(Test1());
EnqueueWork(Test3());


正常开启协程:
StartCoroutine(Test1());
StartCoroutine(Test3());


可以看出,使用协程队列可以更加平滑而且容易控制的去控制协程。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class CoroutineManager : MonoBehaviour
{
    //协程队列
    private Queue
   
   
    
     mCoroutineQueue = new Queue
    
    
     
     ();
    //当前处理的协程 
    private IEnumerator mCurrentWork = null;

    private static CoroutineManager instance;
    public static CoroutineManager Instance
    {
        get { return instance; }
    }

    void Awake()
    {
        instance = this;
    }

    public void EnqueueWork(IEnumerator work)
    {
        mCoroutineQueue.Enqueue(work);
    }

    void Update()
    {
        while (mCoroutineQueue.Count > 30)
            DoWork();

        //如果协程队列>20个,则一次执行3个语块
        if (mCoroutineQueue.Count > 20)
            DoWork();

        //如果协程队列>10个,则一次执行2个语块
        if (mCoroutineQueue.Count > 10)
            DoWork();

        DoWork();
    }

    void DoWork()
    {
        if (mCurrentWork == null && mCoroutineQueue.Count == 0)
            return;

        if (mCurrentWork == null)
        {
            mCurrentWork = mCoroutineQueue.Dequeue();
        }

        //这个协程片段是否执行完毕
        bool mElementFinish = !mCurrentWork.MoveNext();

        if (mElementFinish)
        {
            mCurrentWork = null;
        }
        //如果协程里面嵌套协程
        else if (mCurrentWork.Current is IEnumerator)
        {
            mCurrentWork = (mCurrentWork.Current as IEnumerator);
        }
    }

    #region 这一部分为测试代码
    void Start()
    {
        //协同队列处理
        EnqueueWork(Test1());
        EnqueueWork(Test3());

        //正常开启协同
        //StartCoroutine(Test1());
        //StartCoroutine(Test3());
    }

    IEnumerator Test1()
    {
        Debug.Log(string.Format("第{0}帧:1",Time.frameCount));
        yield return null;
        Debug.Log(string.Format("第{0}帧:2", Time.frameCount));
        yield return null;
        Debug.Log(string.Format("第{0}帧:3", Time.frameCount));

        yield return Test2();
    }

    IEnumerator Test2()
    {
        Debug.Log(string.Format("第{0}帧:4", Time.frameCount));
        yield return null;
        Debug.Log(string.Format("第{0}帧:5", Time.frameCount));
        yield return null;
        Debug.Log(string.Format("第{0}帧:6", Time.frameCount));
    }

    IEnumerator Test3()
    {
        Debug.Log(string.Format("第{0}帧:7", Time.frameCount));
        yield return null;
        Debug.Log(string.Format("第{0}帧:8", Time.frameCount));
        yield return null;
        Debug.Log(string.Format("第{0}帧:9", Time.frameCount));

    }
    #endregion
}
    
    
   
   
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值