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(); } } } } }