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
}
--------------------- 
作者:大城市下的蚂蚁 
来源:CSDN 
原文:https://blog.csdn.net/z625309640/article/details/78080278 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值