/// <summary> /// Sets the update timing. /// </summary> public void SetPhase(RoutinePhase inUpdateMode) { if (m_Chained || m_UpdatePhase == inUpdateMode) { return; } if (inUpdateMode == RoutinePhase.Manual) { if (m_Disposing && !m_Executing) { Dispose(); return; } // Clear out any special yield timing // Yield phases are meaningless in the context of manual updates if (m_YieldPhase != YieldPhase.None) { Manager.Fibers.RemoveFiberFromYieldList(this, m_YieldPhase); m_YieldPhase = YieldPhase.None; } } Manager.Fibers.RemoveFiberFromUpdateList(this, m_UpdatePhase); m_UpdatePhase = inUpdateMode; Manager.Fibers.AddFiberToUpdateList(this, m_UpdatePhase); }
static private string GetPhaseUpdaterName(RoutinePhase inPhase) { switch (inPhase) { case RoutinePhase.FixedUpdate: return(ROUTINE_UPDATER_FIXEDUPDATE); case RoutinePhase.LateUpdate: return(ROUTINE_UPDATER_LATEUPDATE); case RoutinePhase.Update: return(ROUTINE_UPDATER_UPDATE); case RoutinePhase.Manual: return(ROUTINE_UPDATER_MANUAL); case RoutinePhase.CustomUpdate: return(ROUTINE_UPDATER_CUSTOMUPDATE); case RoutinePhase.ThinkUpdate: return(ROUTINE_UPDATER_THINKUPDATE); case RoutinePhase.RealtimeUpdate: return(ROUTINE_UPDATER_REALTIMEUPDATE); default: return(string.Empty); } }
/// <summary> /// Adds a Fiber to the given update list. /// </summary> public void AddFiberToUpdateList(Fiber inFiber, RoutinePhase inUpdate) { switch (inUpdate) { case RoutinePhase.FixedUpdate: AddLast(inFiber, ref m_FixedUpdateList); m_FixedUpdateList.Dirty = true; break; case RoutinePhase.Update: AddLast(inFiber, ref m_UpdateList); m_UpdateList.Dirty = true; break; case RoutinePhase.LateUpdate: AddLast(inFiber, ref m_LateUpdateList); m_LateUpdateList.Dirty = true; break; case RoutinePhase.CustomUpdate: AddLast(inFiber, ref m_CustomUpdateList); m_CustomUpdateList.Dirty = true; break; case RoutinePhase.ThinkUpdate: AddLast(inFiber, ref m_ThinkUpdateList); m_ThinkUpdateList.Dirty = true; break; case RoutinePhase.Manual: AddLast(inFiber, ref m_ManualUpdateList); m_ManualUpdateList.Dirty = true; break; } }
/// <summary> /// Marks an update list to be sorted at the next available time. /// </summary> public void SetUpdateListDirty(RoutinePhase inUpdate) { switch (inUpdate) { case RoutinePhase.FixedUpdate: m_FixedUpdateList.Dirty = true; break; case RoutinePhase.Update: m_UpdateList.Dirty = true; break; case RoutinePhase.LateUpdate: m_LateUpdateList.Dirty = true; break; case RoutinePhase.CustomUpdate: m_CustomUpdateList.Dirty = true; break; case RoutinePhase.ThinkUpdate: m_ThinkUpdateList.Dirty = true; break; case RoutinePhase.RealtimeUpdate: m_RealtimeUpdateList.Dirty = true; break; case RoutinePhase.Manual: m_ManualUpdateList.Dirty = true; break; } }
/// <summary> /// Returns the total number of fibers for the given update list. /// </summary> public int GetUpdateCount(RoutinePhase inUpdate) { switch (inUpdate) { case RoutinePhase.FixedUpdate: return(m_FixedUpdateList.Count); case RoutinePhase.Update: return(m_UpdateList.Count); case RoutinePhase.Manual: return(m_ManualUpdateList.Count); case RoutinePhase.LateUpdate: return(m_LateUpdateList.Count); case RoutinePhase.CustomUpdate: return(m_CustomUpdateList.Count); case RoutinePhase.ThinkUpdate: return(m_ThinkUpdateList.Count); case RoutinePhase.RealtimeUpdate: return(m_RealtimeUpdateList.Count); default: return(0); } }
/// <summary> /// Removes a Fiber from the given update list. /// </summary> public void RemoveFiberFromUpdateList(Fiber inFiber, RoutinePhase inUpdate) { m_MainUpdate.RemoveFromUpdate(this, inUpdate, inFiber); switch (inUpdate) { case RoutinePhase.FixedUpdate: RemoveEntry(inFiber, ref m_FixedUpdateList); break; case RoutinePhase.Update: RemoveEntry(inFiber, ref m_UpdateList); break; case RoutinePhase.LateUpdate: RemoveEntry(inFiber, ref m_LateUpdateList); break; case RoutinePhase.CustomUpdate: RemoveEntry(inFiber, ref m_CustomUpdateList); break; case RoutinePhase.ThinkUpdate: RemoveEntry(inFiber, ref m_ThinkUpdateList); break; case RoutinePhase.Manual: // Nested list is only involved in a manual update m_NestedUpdate.RemoveFromUpdate(this, inUpdate, inFiber); RemoveEntry(inFiber, ref m_ManualUpdateList); break; } }
// Runs a nested update on the given update list (always manual) private void RunUpdateNested(RoutinePhase inUpdateMode, ref UpdateList ioList) { if (ioList.Dirty) { SortUpdateList(ref ioList); ioList.Dirty = false; } m_NestedUpdate.Start(inUpdateMode, ref ioList); bool bPrevUpdating = ioList.Updating; ioList.Updating = true; { while (m_NestedUpdate.Next != -1 && m_NestedUpdate.Counter-- > 0) { Entry e = m_Entries[m_NestedUpdate.Next]; m_NestedUpdate.Next = e.UpdateNext; if (e.Fiber.PrepareUpdate(inUpdateMode)) { e.Fiber.Update(); } } } ioList.Updating = bPrevUpdating; m_NestedUpdate.Clear(); }
public void Clear() { Phase = (RoutinePhase)(-1); Yield = YieldPhase.None; Next = -1; Counter = -1; }
/// <summary> /// Returns if the given list is updating. /// </summary> public bool GetIsUpdating(RoutinePhase inUpdate) { switch (inUpdate) { case RoutinePhase.FixedUpdate: return(m_FixedUpdateList.Updating); case RoutinePhase.Update: return(m_UpdateList.Updating); case RoutinePhase.Manual: return(m_ManualUpdateList.Updating); case RoutinePhase.LateUpdate: return(m_LateUpdateList.Updating); case RoutinePhase.CustomUpdate: return(m_CustomUpdateList.Updating); case RoutinePhase.ThinkUpdate: return(m_ThinkUpdateList.Updating); case RoutinePhase.RealtimeUpdate: return(m_RealtimeUpdateList.Updating); default: return(false); } }
public void RemoveFromUpdate(Table inTable, RoutinePhase inPhase, Fiber inFiber) { if (Counter >= 0 && Next == inFiber.Index && Yield == YieldPhase.None && Phase == inPhase) { Next = inTable.m_Entries[inFiber.Index].UpdateNext; --Counter; } }
public void Start(YieldPhase inYield, ref YieldList inList) { Phase = (RoutinePhase)(-1); Yield = inYield; Next = inList.Head; Counter = inList.Count; }
public void Start(RoutinePhase inPhase, ref UpdateList inList) { Phase = inPhase; Yield = YieldPhase.None; Next = inList.Head; Counter = inList.Count; }
/// <summary> /// Returns if the Fiber will update with the given mode. /// </summary> public bool PrepareUpdate(RoutinePhase inUpdateMode) { if (m_StackPosition < 0 || m_Executing) { return(false); } return(m_UpdatePhase == inUpdateMode); }
/// <summary> /// Clears the update routine for the object and update phase. /// </summary> static public Routine ClearUpdateRoutine(this MonoBehaviour inHost, RoutinePhase inPhase = RoutinePhase.Update) { Manager m = Manager.Get(); if (m != null) { string phaseName = GetPhaseUpdaterName(inPhase); Routine.Stop(inHost, phaseName); } return(Routine.Null); }
/// <summary> /// Sets up a Fiber to run with the given host and routine. /// </summary> public Routine Initialize(MonoBehaviour inHost, IEnumerator inStart, bool inChained) { #if DEVELOPMENT if (Manager.DebugMode && !(inStart is IDisposable)) { throw new ArgumentException("IEnumerators must also implement IDisposable."); } #endif // DEVELOPMENT m_Counter = (byte)(m_Counter == byte.MaxValue ? 1 : m_Counter + 1); m_Handle = (Routine)Table.GenerateID(Index, m_Counter); m_Host = inHost; m_HostIdentity = RoutineIdentity.Find(m_Host.gameObject); m_WaitTime = 0; m_LockCount = 0; m_UnityWait = null; m_Name = null; Priority = 0; // Chained routines are always hosted on the manager if (inChained) { m_Chained = m_HostedByManager = true; } if (!inChained && ReferenceEquals(inHost, Manager.Host)) { m_HostedByManager = true; } if (!ReferenceEquals(m_HostIdentity, null)) { m_HasIdentity = true; } m_TimeScale = 1.0f; m_RootFunction = inStart; m_Stack[m_StackPosition = 0] = inStart; CheckForNesting(inStart); if (!m_Chained) { m_UpdatePhase = Manager.DefaultPhase; Manager.Fibers.AddFiberToUpdateList(this, m_UpdatePhase); } return(m_Handle); }
/// <summary> /// Sets the update timing for the routine. /// Note that if this update is currently running, /// this routine will not execute until the next update. /// </summary> public Routine SetPhase(RoutinePhase inUpdate) { Manager m = Manager.Get(); if (m != null) { Fiber fiber = m.Fibers[this]; if (fiber != null) { fiber.SetPhase(inUpdate); } } return(this); }
/// <summary> /// Updates all fibers in the given list. /// </summary> public void RunUpdate(RoutinePhase inUpdateMode) { switch (inUpdateMode) { case RoutinePhase.FixedUpdate: RunUpdate(RoutinePhase.FixedUpdate, ref m_FixedUpdateList); break; case RoutinePhase.Update: RunUpdate(RoutinePhase.Update, ref m_UpdateList); break; case RoutinePhase.LateUpdate: RunUpdate(RoutinePhase.LateUpdate, ref m_LateUpdateList); break; case RoutinePhase.CustomUpdate: RunUpdate(RoutinePhase.CustomUpdate, ref m_CustomUpdateList); break; case RoutinePhase.ThinkUpdate: RunUpdate(RoutinePhase.ThinkUpdate, ref m_ThinkUpdateList); break; case RoutinePhase.RealtimeUpdate: RunUpdate(RoutinePhase.RealtimeUpdate, ref m_RealtimeUpdateList); break; case RoutinePhase.Manual: if (m_MainUpdate.Counter >= 0) { RunUpdateNested(RoutinePhase.Manual, ref m_ManualUpdateList); } else { RunUpdate(RoutinePhase.Manual, ref m_ManualUpdateList); } break; } }
private void RenderStats(RoutineStats inStats, bool inbCanAdjust, bool inbNested) { if (!inbNested) { // Render id EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField("ID/", GUILayout.Width(FIELD_NAME_WIDTH)); uint handleID = (uint)inStats.Handle; uint index = handleID & Table.INDEX_MASK; uint counter = (handleID & Table.COUNTER_MASK) >> Table.COUNTER_SHIFT; EditorGUILayout.LabelField(index.ToString() + " (" + counter.ToString("X2") + ")", GUILayout.ExpandWidth(true)); } EditorGUILayout.EndHorizontal(); // Render name EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField("NAME/", GUILayout.Width(FIELD_NAME_WIDTH)); if (!inbCanAdjust) { GUI.enabled = false; } string newName = EditorGUILayout.TextField(inStats.Name, GUILayout.ExpandWidth(true)); if (newName != inStats.Name) { inStats.Handle.SetName(newName); } GUI.enabled = true; } EditorGUILayout.EndHorizontal(); } if (!inbNested && !ReferenceEquals(inStats.Host, null)) { // Render host EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField("HOST/", GUILayout.Width(FIELD_NAME_WIDTH)); GUI.enabled = false; EditorGUILayout.ObjectField(inStats.Host, typeof(MonoBehaviour), true, GUILayout.ExpandWidth(true)); GUI.enabled = true; } EditorGUILayout.EndHorizontal(); } // Current state EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField("STATUS/", GUILayout.Width(FIELD_NAME_WIDTH)); EditorGUILayout.LabelField(inStats.State, GUILayout.ExpandWidth(true)); } EditorGUILayout.EndHorizontal(); // Time Scale if (!inbNested) { EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField("TIMESCALE/", GUILayout.Width(FIELD_NAME_WIDTH)); if (!inbCanAdjust) { GUI.enabled = false; } #if SUPPORTS_DELAYEDFIELDS float timeScale = EditorGUILayout.DelayedFloatField(inStats.TimeScale, GUILayout.ExpandWidth(true)); #else float timeScale = EditorGUILayout.FloatField(inStats.TimeScale, GUILayout.ExpandWidth(true)); #endif if (timeScale < 0) { timeScale = 0; } if (timeScale != inStats.TimeScale) { inStats.Handle.SetTimeScale(timeScale); } GUI.enabled = true; } EditorGUILayout.EndHorizontal(); } // Priority if (!inbNested) { EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField("PRIORITY/", GUILayout.Width(FIELD_NAME_WIDTH)); if (!inbCanAdjust) { GUI.enabled = false; } #if SUPPORTS_DELAYEDFIELDS int priority = EditorGUILayout.DelayedIntField(inStats.Priority, GUILayout.ExpandWidth(true)); #else int priority = EditorGUILayout.IntField(inStats.Priority, GUILayout.ExpandWidth(true)); #endif if (priority != inStats.Priority) { inStats.Handle.SetPriority(priority); } GUI.enabled = true; } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField("PHASE/", GUILayout.Width(FIELD_NAME_WIDTH)); if (!inbCanAdjust) { GUI.enabled = false; } RoutinePhase update = (RoutinePhase)EditorGUILayout.EnumPopup(inStats.Phase, GUILayout.ExpandWidth(true)); if (update != inStats.Phase) { inStats.Handle.SetPhase(update); } GUI.enabled = true; } EditorGUILayout.EndHorizontal(); } // Current Function Name EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField("FUNCTION/" + inStats.StackDepth + "/", GUILayout.Width(FIELD_NAME_WIDTH)); EditorGUILayout.LabelField(inStats.Function == null ? "[Null]" : inStats.Function, GUILayout.ExpandWidth(true)); } EditorGUILayout.EndHorizontal(); if (inStats.State != RoutineState.Disposing && inbCanAdjust) { // Functions EditorGUILayout.BeginHorizontal(); { if (GUILayout.Button("Pause")) { inStats.Handle.Pause(); } if (GUILayout.Button("Resume")) { inStats.Handle.Resume(); } if (GUILayout.Button("Stop")) { inStats.Handle.Stop(); } } EditorGUILayout.EndHorizontal(); } if (inStats.Nested != null && inStats.Nested.Length > 0) { EditorGUILayout.LabelField("NESTED/"); BeginIndent(); RenderStatGroup(inStats.Nested, inbCanAdjust, true); EndIndent(); } }
/// <summary> /// Runs the Fiber one frame. /// Will dispose itself if requested. /// Returns if still running. /// </summary> public bool Update(YieldPhase inYieldUpdate = YieldPhase.None) { // We don't support recursive Fiber updates if (m_Executing) { return(true); } if (m_StackPosition < 0) { return(false); } if (m_Disposing || (!m_HostedByManager && !m_Host)) { Dispose(); return(false); } if (inYieldUpdate != YieldPhase.None && m_YieldFrameDelay > 0) { --m_YieldFrameDelay; return(true); } if (IsPaused() || m_UnityWait != null) { return(true); } if (m_YieldPhase != inYieldUpdate) { return(true); } if (inYieldUpdate != YieldPhase.None) { Manager.Fibers.RemoveFiberFromYieldList(this, m_YieldPhase); m_YieldPhase = YieldPhase.None; // If we're in a manual update, don't proceed from here if (m_UpdatePhase == RoutinePhase.Manual) { return(true); } } // If we're a chained routine, just accept // the parent's delta time. if (!m_Chained) { ApplyDeltaTime(); } else if (inYieldUpdate != YieldPhase.None) { m_RootFiber.ApplyDeltaTime(); } if (m_WaitTime > 0) { m_WaitTime -= Manager.Frame.DeltaTime; if (m_WaitTime > 0) { return(true); } // We don't modify delta time in the fixed update phase, // to preserve a consistent delta time within fixed update. if (m_UpdatePhase != RoutinePhase.FixedUpdate && inYieldUpdate != YieldPhase.WaitForFixedUpdate) { Manager.Frame.DeltaTime += m_WaitTime; } m_WaitTime = 0; } bool bExecuteStack = true; while (bExecuteStack) { bExecuteStack = false; // Set this flag to prevent updating this routine mid-execution m_Executing = true; IEnumerator current = m_Stack[m_StackPosition]; bool bMovedNext = false; if (Manager.HandleExceptions || m_HandleExceptions || (m_Chained && m_RootFiber.m_HandleExceptions)) { try { bMovedNext = current.MoveNext(); } catch (Exception e) { Debug.LogException(e); Routine.ExceptionHandler exceptionHandler = m_OnException; if (m_Chained) { exceptionHandler = m_RootFiber.m_OnException; m_RootFiber.m_Disposing = true; } if (exceptionHandler != null) { exceptionHandler(e); } m_Disposing = true; } } else { bMovedNext = current.MoveNext(); } m_Executing = false; // Don't check for the object being destroyed. // Destroy won't go into effect until after // all the Fibers are done processing anyways. if (m_Disposing) { Dispose(); return(false); } if (bMovedNext) { object result = current.Current; if (result == null) { return(true); } IntPtr resultType = result.GetType().TypeHandle.Value; // Check all the easy-to-identify result types if (resultType == TYPEHANDLE_INT) { m_WaitTime = (int)result; return(true); } if (resultType == TYPEHANDLE_FLOAT) { m_WaitTime = (float)result; return(true); } if (resultType == TYPEHANDLE_DOUBLE) { m_WaitTime = (float)(double)result; return(true); } if (resultType == TYPEHANDLE_ROUTINE) { IEnumerator waitSequence = ((Routine)result).Wait(); if (waitSequence != null) { if (m_StackPosition == m_StackSize - 1) { Array.Resize(ref m_Stack, m_StackSize *= 2); } m_Stack[++m_StackPosition] = waitSequence; } return(true); } if (resultType == TYPEHANDLE_WWW) { // Disable obsolete WWW warning #pragma warning disable 612, 618 m_UnityWait = Manager.Host.StartCoroutine(UnityWait((WWW)result)); return(true); // Restore obsolete WWW warning #pragma warning restore 612, 618 } if (resultType == TYPEHANDLE_COMMAND) { Routine.Command c = (Routine.Command)result; switch (c) { case Routine.Command.Pause: Pause(); return(true); case Routine.Command.Stop: Stop(); Dispose(); return(false); case Routine.Command.BreakAndResume: m_Stack[m_StackPosition--] = null; ((IDisposable)current).Dispose(); if (m_StackPosition < 0) { Dispose(); return(false); } bExecuteStack = true; break; case Routine.Command.Continue: bExecuteStack = true; break; } if (!bExecuteStack) { return(true); } continue; } if (resultType == TYPEHANDLE_DECORATOR) { RoutineDecorator decorator = (RoutineDecorator)result; IEnumerator decoratedEnumerator = decorator.Enumerator; bExecuteStack = (decorator.Flags & RoutineDecoratorFlag.Inline) != 0; if (decoratedEnumerator != null) { // Check if we need to resize the stack if (m_StackPosition == m_StackSize - 1) { Array.Resize(ref m_Stack, m_StackSize *= 2); } m_Stack[++m_StackPosition] = decorator; CheckForNesting(decoratedEnumerator); } if (!bExecuteStack) { return(true); } continue; } // Check for yield timing changes if (m_UpdatePhase != RoutinePhase.Manual) { bool bApplyYieldDelay = !Manager.IsUpdating(RoutinePhase.Manual) && inYieldUpdate == YieldPhase.None; if (resultType == TYPEHANDLE_ROUTINEPHASE) { RoutinePhase phase = (RoutinePhase)result; switch (phase) { case RoutinePhase.FixedUpdate: { Manager.Fibers.AddFiberToYieldList(this, YieldPhase.WaitForFixedUpdate); Manager.Host.WaitForFixedUpdate(); m_YieldPhase = YieldPhase.WaitForFixedUpdate; m_YieldFrameDelay = bApplyYieldDelay && m_UpdatePhase == RoutinePhase.FixedUpdate && Manager.IsUpdating(RoutinePhase.FixedUpdate) ? 1 : 0; return(true); } case RoutinePhase.LateUpdate: { Manager.Fibers.AddFiberToYieldList(this, YieldPhase.WaitForLateUpdate); m_YieldPhase = YieldPhase.WaitForLateUpdate; m_YieldFrameDelay = bApplyYieldDelay && m_UpdatePhase == RoutinePhase.LateUpdate && Manager.IsUpdating(RoutinePhase.LateUpdate) ? 1 : 0; return(true); } case RoutinePhase.Update: { Manager.Fibers.AddFiberToYieldList(this, YieldPhase.WaitForUpdate); m_YieldPhase = YieldPhase.WaitForUpdate; m_YieldFrameDelay = bApplyYieldDelay && m_UpdatePhase == RoutinePhase.Update && Manager.IsUpdating(RoutinePhase.Update) ? 1 : 0; return(true); } case RoutinePhase.CustomUpdate: { Manager.Fibers.AddFiberToYieldList(this, YieldPhase.WaitForCustomUpdate); m_YieldPhase = YieldPhase.WaitForCustomUpdate; m_YieldFrameDelay = bApplyYieldDelay && m_UpdatePhase == RoutinePhase.CustomUpdate && Manager.IsUpdating(RoutinePhase.CustomUpdate) ? 1 : 0; return(true); } case RoutinePhase.ThinkUpdate: { Manager.Fibers.AddFiberToYieldList(this, YieldPhase.WaitForThinkUpdate); m_YieldPhase = YieldPhase.WaitForThinkUpdate; m_YieldFrameDelay = bApplyYieldDelay && m_UpdatePhase == RoutinePhase.ThinkUpdate && Manager.IsUpdating(RoutinePhase.ThinkUpdate) ? 1 : 0; return(true); } case RoutinePhase.RealtimeUpdate: { Manager.Fibers.AddFiberToYieldList(this, YieldPhase.WaitForRealtimeUpdate); m_YieldPhase = YieldPhase.WaitForRealtimeUpdate; m_YieldFrameDelay = bApplyYieldDelay && m_UpdatePhase == RoutinePhase.RealtimeUpdate && Manager.IsUpdating(RoutinePhase.RealtimeUpdate) ? 1 : 0; return(true); } case RoutinePhase.Manual: default: { // Yielding a manual will not do anything return(true); } } } if (resultType == TYPEHANDLE_WAITFORENDOFFRAME) { Manager.Fibers.AddFiberToYieldList(this, YieldPhase.WaitForEndOfFrame); m_YieldPhase = YieldPhase.WaitForEndOfFrame; m_YieldFrameDelay = 0; return(true); } if (resultType == TYPEHANDLE_WAITFORFIXEDUPDATE) { Manager.Fibers.AddFiberToYieldList(this, YieldPhase.WaitForFixedUpdate); Manager.Host.WaitForFixedUpdate(); m_YieldPhase = YieldPhase.WaitForFixedUpdate; m_YieldFrameDelay = bApplyYieldDelay && m_UpdatePhase == RoutinePhase.FixedUpdate && Manager.IsUpdating(RoutinePhase.FixedUpdate) ? 1 : 0; return(true); } if (resultType == TYPEHANDLE_WAITFORLATEUPDATE) { Manager.Fibers.AddFiberToYieldList(this, YieldPhase.WaitForLateUpdate); m_YieldPhase = YieldPhase.WaitForLateUpdate; m_YieldFrameDelay = bApplyYieldDelay && m_UpdatePhase == RoutinePhase.LateUpdate && Manager.IsUpdating(RoutinePhase.LateUpdate) ? 1 : 0; return(true); } if (resultType == TYPEHANDLE_WAITFORUPDATE) { Manager.Fibers.AddFiberToYieldList(this, YieldPhase.WaitForUpdate); m_YieldPhase = YieldPhase.WaitForUpdate; m_YieldFrameDelay = bApplyYieldDelay && m_UpdatePhase == RoutinePhase.Update && Manager.IsUpdating(RoutinePhase.Update) ? 1 : 0; return(true); } if (resultType == TYPEHANDLE_WAITFORCUSTOMUPDATE) { Manager.Fibers.AddFiberToYieldList(this, YieldPhase.WaitForCustomUpdate); m_YieldPhase = YieldPhase.WaitForCustomUpdate; m_YieldFrameDelay = bApplyYieldDelay && m_UpdatePhase == RoutinePhase.CustomUpdate && Manager.IsUpdating(RoutinePhase.CustomUpdate) ? 1 : 0; return(true); } if (resultType == TYPEHANDLE_WAITFORTHINKUPDATE) { Manager.Fibers.AddFiberToYieldList(this, YieldPhase.WaitForThinkUpdate); m_YieldPhase = YieldPhase.WaitForThinkUpdate; m_YieldFrameDelay = bApplyYieldDelay && m_UpdatePhase == RoutinePhase.ThinkUpdate && Manager.IsUpdating(RoutinePhase.ThinkUpdate) ? 1 : 0; return(true); } if (resultType == TYPEHANDLE_WAITFORREALTIMEUPDATE) { Manager.Fibers.AddFiberToYieldList(this, YieldPhase.WaitForRealtimeUpdate); m_YieldPhase = YieldPhase.WaitForRealtimeUpdate; m_YieldFrameDelay = bApplyYieldDelay && m_UpdatePhase == RoutinePhase.RealtimeUpdate && Manager.IsUpdating(RoutinePhase.RealtimeUpdate) ? 1 : 0; return(true); } } if (WAITFORSECONDS_BYPASS && resultType == TYPEHANDLE_WAITFORSECONDS) { m_WaitTime = (float)FIELD_WAITFORSECONDS_SECONDS.GetValue(result); return(true); } // Check for the subclassable types #if SUPPORTS_CUSTOMYIELDINSTRUCTION CustomYieldInstruction customInstruction = result as CustomYieldInstruction; if (customInstruction != null) { m_UnityWait = Manager.Host.StartCoroutine(UnityWait(customInstruction)); return(true); } #endif YieldInstruction instruction = result as YieldInstruction; if (instruction != null) { m_UnityWait = Manager.Host.StartCoroutine(UnityWait(instruction)); return(true); } IFuture future = result as IFuture; if (future != null) { if (!future.IsDone()) { IEnumerator waitSequence = future.Wait(); if (waitSequence != null) { if (m_StackPosition == m_StackSize - 1) { Array.Resize(ref m_Stack, m_StackSize *= 2); } m_Stack[++m_StackPosition] = waitSequence; } } return(true); } IEnumerator enumerator = result as IEnumerator; if (enumerator != null) { // Check if we need to resize the stack if (m_StackPosition == m_StackSize - 1) { Array.Resize(ref m_Stack, m_StackSize *= 2); } m_Stack[++m_StackPosition] = enumerator; CheckForNesting(enumerator); return(true); } } else { bExecuteStack = current is RoutineDecorator && (((RoutineDecorator)current).Flags & RoutineDecoratorFlag.Inline) != 0; m_Stack[m_StackPosition--] = null; ((IDisposable)current).Dispose(); if (m_StackPosition < 0) { Dispose(); return(false); } } } return(true); }
/// <summary> /// Is the manager in the middle of updating the given update list. /// </summary> public bool IsUpdating(RoutinePhase inUpdate) { return(Fibers.GetIsUpdating(inUpdate)); }
/// <summary> /// Cleans up the Fiber. /// </summary> public void Dispose() { if ((uint)m_Handle == 0) { return; } if (m_UnityWait != null) { Manager.Host.StopCoroutine(m_UnityWait); m_UnityWait = null; } bool bKilled = m_StackPosition >= 0; bool bChained = m_Chained; ClearStack(); m_Handle = Routine.Null; m_Host = null; m_HostIdentity = null; // If this is chained and we have a parallel if (bChained && m_Container != null) { m_Container.RemoveFiber(this); } m_Chained = m_Disposing = m_HasIdentity = m_Paused = m_IgnoreObjectTimescale = m_HostedByManager = m_IgnoreObjectActive = m_Executing = false; m_WaitTime = 0; m_LockCount = 0; m_Name = null; Priority = 0; m_Container = null; m_RootFiber = null; m_TimeScale = 1.0f; m_YieldFrameDelay = 0; if (m_YieldPhase != YieldPhase.None) { Manager.Fibers.RemoveFiberFromYieldList(this, m_YieldPhase); m_YieldPhase = YieldPhase.None; } if (!bChained) { Manager.Fibers.RemoveFiberFromUpdateList(this, m_UpdatePhase); } Manager.RecycleFiber(this, bChained); m_UpdatePhase = Manager.DefaultPhase; m_OnException = null; m_HandleExceptions = false; if (bKilled) { m_OnComplete = null; Action onStop = m_OnStop; m_OnStop = null; if (onStop != null) { onStop(); } } else { m_OnStop = null; Action onComplete = m_OnComplete; m_OnComplete = null; if (onComplete != null) { onComplete(); } } }
/// <summary> /// Returns the update routine associated with the object and update phase. /// </summary> static public Routine GetUpdateRoutine(this MonoBehaviour inHost, RoutinePhase inPhase = RoutinePhase.Update) { return(Routine.Find(inHost, GetPhaseUpdaterName(inPhase))); }
/// <summary> /// Sets the update routine for the object and update phase. /// </summary> static public Routine SetUpdateRoutine(this MonoBehaviour inHost, IEnumerator inUpdateLoop, RoutinePhase inPhase = RoutinePhase.Update) { Manager m = Manager.Get(); if (m != null) { string phaseName = GetPhaseUpdaterName(inPhase); Routine routine = Routine.Find(inHost, phaseName) .Replace(inHost, inUpdateLoop).SetPhase(inPhase); Fiber fiber = m.Fibers[routine]; if (fiber != null) { fiber.SetNameUnchecked(phaseName); } return(routine); } return(Routine.Null); }
/// <summary> /// Updates all running routines. /// </summary> public void Update(float inDeltaTime, RoutinePhase inPhase) { Frame.IncrementSerial(); Frame.ResetTime(inDeltaTime, TimeScale); Frame.PauseMask = m_QueuedPauseMask; if (m_GroupTimescaleDirty) { m_GroupTimescaleDirty = false; Array.Copy(m_QueuedGroupTimescale, Frame.GroupTimeScale, Routine.MAX_GROUPS); } bool bPrevUpdating = m_Updating; m_Updating = true; { #if DEVELOPMENT if (DebugMode && !bPrevUpdating && ProfilingEnabled) { m_UpdateTimer.Reset(); m_UpdateTimer.Start(); if (m_NeedsSnapshot) { m_Snapshot = GetRoutineStats(); m_NeedsSnapshot = false; } if (!Paused && !SystemPaused && Fibers.GetUpdateCount(inPhase) > 0) { Fibers.RunUpdate(inPhase); Frame.ResetTimeScale(); } m_UpdateTimer.Stop(); m_TotalUpdateTime += m_UpdateTimer.ElapsedTicks; if (inPhase == RoutinePhase.LateUpdate) { ++m_TotalUpdateFrames; if (Time.unscaledTime >= m_LastProfileLogTime + 10f) { m_LastProfileLogTime = Time.unscaledTime; m_LogBuilder.Length = 0; m_LogBuilder.Append("Running: ").Append(Fibers.TotalActive) .Append('/').Append(m_MaxConcurrent) .Append('/').Append(Fibers.TotalCapacity) .Append("; Avg Update: ").Append((m_TotalUpdateTime / 10000f) / m_TotalUpdateFrames).Append("ms"); Log(string.Empty); } if (m_TotalUpdateFrames >= MAX_UPDATE_SAMPLES || m_UpdateTimer.ElapsedMilliseconds > MAX_UPDATE_MS) { m_TotalUpdateFrames = 0; m_TotalUpdateTime = 0; } } } else #endif // DEVELOPMENT { if (!Paused && !SystemPaused && Fibers.GetUpdateCount(inPhase) > 0) { Fibers.RunUpdate(inPhase); Frame.ResetTimeScale(); } } } m_Updating = bPrevUpdating; if (!m_Updating) { if (m_Destroying) { m_Destroying = false; Destroy(); } } }
/// <summary> /// Sets the update routine for the object and update phase. /// </summary> static public Routine SetUpdateRoutineGenerator(this MonoBehaviour inHost, Func <IEnumerator> inUpdateFunc, RoutinePhase inPhase = RoutinePhase.Update) { string phaseName = GetPhaseUpdaterName(inPhase); Routine routine = Routine.Find(inHost, phaseName).Replace(Routine.StartLoopRoutine(inHost, inUpdateFunc)).SetPhase(inPhase); Fiber fiber = Manager.Get().Fibers[routine]; if (fiber != null) { fiber.SetNameUnchecked(phaseName); } return(routine); }