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

来源:互联网 发布:php 通过域名获取ip 编辑:程序博客网 时间:2024/06/05 08:55
游戏开发过程中经常会遇到要加载一片场景资源的情况,先不考虑如何加载的情况,对于一大片场景的加载和显示,如果在一帧内完成的话,对性能会有很大的小号,造成瞬间帧率下降,产生性能峰值。
一般这种不需要实时性的加载都会分帧处理,把压力平摊下去,为了使加载过程更加平滑与受控,博主写一个协程队列去控制我们加载过程中协程的调用顺序与次数,更好的平滑我们的加载过程。
因为这里协程的调用是使用迭代器的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}
原创粉丝点击