using UnityEngine;
using System.Collections;
using System.Collections.Generic;
///
/// 所有CCoroutine返回yield指令对象的基类
///
public class CCoroutineYieldBase
{
}
///
/// 排他性的yield,在这个yield到下个yield完成之前,不允许其他的协程执行
///
public class CHoldForSecond : CCoroutineYieldBase
{
public float m_interval = -1;
///
/// 间隔时间
///
/// 间隔时间,yield return之后至少要过这么久才又会调用过来,单位秒,在这段时间内主线程sleep等待
public CHoldForSecond(float interval = 0f)
{
m_interval = interval;
}
}
///
/// 排他性的yield,在这个yield到下个yield完成之前,不允许其他的协程执行
///
public class CWaitForSecond : CCoroutineYieldBase
{
public float m_interval = -1;
///
/// 间隔时间
///
/// 间隔时间,yield return之后至少要过这么久才又会调用过来,单位秒,在这段时间内主线程继续开始循环
public CWaitForSecond(float interval = -1)
{
m_interval = interval;
}
}
///
/// 排他性的yield,在这个yield到下个yield完成之前,不允许其他的协程执行
///
public class CWaitForNextFrame : CCoroutineYieldBase
{
}
///
/// 之所以CCorourtineManager还需要用这个Monobehaviour去调用,就是由于如果CCorourtineManager直接是Monobehaviour,会自带
/// StartCoroutine方法,而那个是我们的类不希望开发人员去调用的
///
public class ____CCorourtineManagerMonobehaviour : SingletonMono<____CCorourtineManagerMonobehaviour>
{
public CCoroutineManager s_smartCoroutine = null;
void Update()
{
if (null != s_smartCoroutine)
{
s_smartCoroutine.Update();
}
}
}
///
/// 代表一个协程任务
///
public class CCoroutine
{
public IEnumerator iter = null;
public CCoroutine(IEnumerator it)
{
iter = it;
}
public void Stop()
{
iter = null;
}
}
///
/// 智能协程,能够很好利用每一帧的时间来做事,又尽量不卡渲染,用于平滑Loading时候的动画
///
public class CCoroutineManager : Singleton
{
private System.DateTime m_lastFrameTime;
private System.DateTime m_waitTillTime;
private long m_lastTimeUpdateBeginTime = 0;
private LinkedList m_execlusiveCoroutineList = new LinkedList();
private int m_frameRate = 0;
private double m_deltaMillSecondsPerFrame = 0;
int sleepTime = 0;
int WaitTime = 0;
public override void Init()
{
____CCorourtineManagerMonobehaviour.Instance.s_smartCoroutine = this;
m_lastFrameTime = System.DateTime.Now;
m_waitTillTime = System.DateTime.Now;
m_frameRate = 30;
m_deltaMillSecondsPerFrame = standardDeltaTime * 1;
}
private double standardDeltaTime
{
get
{
return 1000f / 30f;
}
}
public void Update()
{
//WaitFormSeconds的时间还没到
if (System.DateTime.Now <= m_waitTillTime)
{
return;
}
//ReEvaluateTimeCost();
m_lastFrameTime = System.DateTime.Now;
while ((System.DateTime.Now - m_lastFrameTime).TotalMilliseconds < m_deltaMillSecondsPerFrame
&& m_execlusiveCoroutineList.Count > 0)
{
LinkedListNode node = m_execlusiveCoroutineList.Last;
var coroutine = node.Value.iter;
if (!coroutine.MoveNext())
{
//协程已经执行完
m_execlusiveCoroutineList.Remove(node);
continue;
}
object handle = coroutine.Current;
if (handle == null)
{
//协程已经执行完
m_execlusiveCoroutineList.Remove(node);
continue;
}
if (handle is CCoroutine)
{
continue;
}
if (handle is CHoldForSecond)
{
ProcessHoldForSeconds(handle as CHoldForSecond);
}
else if (handle is CWaitForSecond)
{
ProcessWaitForSeconds(handle as CWaitForSecond);
break;
}
else if (handle is CWaitForNextFrame)
{
break;
}
else
{
DebugHelper.LogError("CCoroutine不支持" + handle.GetType() + "类型的yield return指令,请明确您需要做什么");
}
}
m_lastFrameTime = System.DateTime.Now;
}
///
/// 重新评估m_deltaTimePerFrame是否合理,是否把帧之间的时间利用得当
///
private System.DateTime m_lastEvaluateTime = System.DateTime.Now;
private bool m_evaluateStart = false;
private void ReEvaluateTimeCost()
{
if (m_evaluateStart == false)
{
m_lastEvaluateTime = System.DateTime.Now;
m_evaluateStart = true;
return;
}
System.DateTime evaluateTime = System.DateTime.Now;
double diff = (evaluateTime - m_lastEvaluateTime).TotalMilliseconds;
m_lastEvaluateTime = evaluateTime;
if (diff > standardDeltaTime)
{
m_deltaMillSecondsPerFrame = System.Math.Max(standardDeltaTime * 0.3f, m_deltaMillSecondsPerFrame - (diff - standardDeltaTime));
}
else if (m_deltaMillSecondsPerFrame < standardDeltaTime * 0.75f)
{
m_deltaMillSecondsPerFrame += 1; //如果用于loading的时间太短,就尝试开始增加
}
}
private void ProcessHoldForSeconds(CHoldForSecond handle)
{
if (handle.m_interval > 0)
{
sleepTime += (int)(handle.m_interval * 1000);
System.Threading.Thread.Sleep((int)(handle.m_interval * 1000f));
}
}
private void ProcessWaitForSeconds(CWaitForSecond handle)
{
if (handle.m_interval > 0)
{
WaitTime += (int)(handle.m_interval * 1000);
m_waitTillTime = System.DateTime.Now.AddSeconds(handle.m_interval);
}
}
///
/// 开始协程
///
///
public CCoroutine StartCoroutine(IEnumerator coroutine)
{
CCoroutine cor = new CCoroutine(coroutine);
m_execlusiveCoroutineList.AddLast(cor);
return cor;
}
///
/// 停止一个协程
///
///
public void StopCoroutine(CCoroutine c, bool stopChild = true)
{
if (c != null)
{
c.Stop();
bool foundChild = false;
var iter = m_execlusiveCoroutineList.GetEnumerator();
while (iter.MoveNext())
{
if (iter.Current == c)
{
foundChild = true;
break;
}
}
if (!stopChild)
{
if (foundChild)
{
m_execlusiveCoroutineList.Remove(iter.Current);
}
return;
}
else
{
if (foundChild)
{
CCoroutine last = m_execlusiveCoroutineList.Last.Value;
while (last != c)
{
m_execlusiveCoroutineList.RemoveLast();
last = m_execlusiveCoroutineList.Last.Value;
}
m_execlusiveCoroutineList.RemoveLast();
}
}
}
}
}