/// Return value indicate whether this coroutine is dead. internal bool _Update(float fTime) { bool bIsDead = false; try { if (_onUpdate != null && state == CoroutineState.Running) { _onUpdate(_pCurrentInstruction); } } catch (Exception e) { _HandleException(new CoroutineException(e, this)); bIsDead = true; } bool bIsComplete = false; if (_state < CoroutineState.Running) { if (_state == CoroutineState.Paused) { return(false); } else if (_state == CoroutineState.Stopped) { bIsComplete = true; } else if (_state == CoroutineState.Disposed) { /// Occurred when a manual coroutine is Removed. return(true); } else { Debugger.Assert(false); } } try { _pCoroutineMgr._CoEnterLogStack.Push(this); if (bIsComplete) { if (!__bIsManualStopped) { __doComplete(); } return(true); } ///------------------- bIsDead = false; Debugger.Assert(_pCurrentInstruction != null); Debugger.DebugSection(() => { if (_pCurrentInstruction.GetInstructionType() == YieldInstructionType.Coroutine) { var coroutine = _pCurrentInstruction as Coroutine; Debugger.ConditionalAssert(coroutine._bPooled, coroutine.state != CoroutineState.Freed); } }); if (_pCurrentInstruction.GetInstructionType() == YieldInstructionType.ReturnValue) { bIsDead = true; _ReturnValue pReturnValue = _pCurrentInstruction as _ReturnValue; __doComplete(pReturnValue.returnValue); } else { _pCurrentInstruction.Update(fTime); if (_pCurrentInstruction.IsDone()) { if (_onYieldDone != null) { _onYieldDone(_pCurrentInstruction); } if (state != CoroutineState.Stopped) { Debugger.Assert(_pCurrentInstruction != null); _pCurrentInstruction.Stop(); if (!_pCoroutineFunc.MoveNext()) { _pCurrentInstruction.DecRef(); _pCurrentInstruction = null; bIsDead = true; __doComplete(); } else { if (_state != CoroutineState.Stopped) { Debugger.Assert(_state != CoroutineState.Freed && _state != CoroutineState.Disposed); Debugger.Assert(_pCoroutineFunc != null, "Coroutine function is null but still in update, you may be operated on a dead coroutine!!!"); /// Why defRef here? Because MoveNext() may cause current instruction _pCurrentInstruction.DecRef(); _pCurrentInstruction = _pCoroutineFunc.Current as IYieldInstruction; if (_pCurrentInstruction == null) { throw new UnsupportedYieldInstruction(); } _pCurrentInstruction.Start(fTime); _pCurrentInstruction.IncRef(); } } } } } } catch (Exception e) { Debugger.Assert(!(e is CoroutineException)); _HandleException(new CoroutineException(e, this)); bIsDead = true; } finally { Debugger.Assert(_pCoroutineMgr._CoEnterLogStack.Peek() == this); _pCoroutineMgr._CoEnterLogStack.Pop(); } return(bIsDead); }
internal void _Start(IEnumerator pCoroutineFunc) { Debugger.Assert(GetRef() != 0); _Parent = _pCoroutineMgr.Current(); if (_Parent != null) { _Parent._DoChildCoStart(this); } Debugger.Assert(_state != CoroutineState.Disposed); if (_state == CoroutineState.Running || _state == CoroutineState.Paused) { Stop(); } try { _pCoroutineMgr._CoEnterLogStack.Push(this); if (!_bInQueue) { CoroutineMgr._Instance._AddToQueue(this); } _pCoroutineFunc = pCoroutineFunc; if (_onStart != null) { _onStart(this); } _state = CoroutineState.Running; if (_pCoroutineFunc.MoveNext()) { /// 如果子Coroutine的第一行代码抛出异常,_state会被设置为Stopped if (_state != CoroutineState.Stopped) { Debugger.Assert(_state != CoroutineState.Disposed && _state != CoroutineState.Freed); _pCurrentInstruction = _pCoroutineFunc.Current as IYieldInstruction; if (_pCurrentInstruction == null) { throw new UnsupportedYieldInstruction(); } _pCurrentInstruction.Start(scalable ? _pCoroutineMgr._Time : _pCoroutineMgr._RealTime); _pCurrentInstruction.IncRef(); } } else { /// When coroutine has the 'yield break' at first line, will reach here. /// The onStop will be called at next _Update. _state = CoroutineState.Stopped; } } catch (Exception e) { if (e is CoroutineException) { _HandleException(e as CoroutineException); } else { _HandleException(new CoroutineException(e, this)); } } finally { Debugger.Assert(_pCoroutineMgr._CoEnterLogStack.Peek() == this); _pCoroutineMgr._CoEnterLogStack.Pop(); } }