IEnumerator WaitForPreviousTransition(StateMapping nextState) { while (isInTransition) { yield return(null); } ChangeState((T)nextState.state); }
private IEnumerator ChangeToNewStateRoutine(StateMapping newState, MonoFSMStateTransitionOption transition) { destinationState = newState; if (currentState != null) { if (currentState.HasExitRoutine) { exitRoutine = currentState.ExitRoutine(); if (exitRoutine != null && transition != MonoFSMStateTransitionOption.Overwrite) { yield return(engine.StartCoroutine(exitRoutine)); } exitRoutine = null; } else { currentState.ExitCall(); } currentState.Finally(); } lastState = currentState; currentState = destinationState; if (currentState != null) { if (currentState.HasEnterRoutine) { enterRoutine = currentState.EnterRoutine(); if (enterRoutine != null) { yield return(engine.StartCoroutine(enterRoutine)); } enterRoutine = null; } else { currentState.EnterCall(); } if (OnFSMStateChangedEventHandler != null) { OnFSMStateChangedEventHandler((T)currentState.state); } } isInTransition = false; }
public MonoFSM(MonoFSMRunner engine, MonoBehaviour component) { this.engine = engine; this.component = component; var values = Enum.GetValues(typeof(T)); if (values.Length < 1) { throw new ArgumentException("必须至少定义一个枚举的,亲!"); } stateLookup = new Dictionary <object, StateMapping>(); for (int i = 0; i < values.Length; i++) { var mapping = new StateMapping((Enum)values.GetValue(i)); stateLookup.Add(mapping.state, mapping); } var methods = component.GetType().GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic); var separator = "_".ToCharArray(); for (int i = 0; i < methods.Length; i++) { if (methods[i].GetCustomAttributes(typeof(CompilerGeneratedAttribute), true).Length != 0) { continue; } var names = methods[i].Name.Split(separator); if (names.Length <= 1) { continue; } Enum key; try { key = (Enum)Enum.Parse(typeof(T), names[0]); } catch (ArgumentException) { continue; } var targetState = stateLookup[key]; switch (names[1]) { case "Enter": if (methods[i].ReturnType == typeof(IEnumerator)) { targetState.HasEnterRoutine = true; targetState.EnterRoutine = CreateDelegate <Func <IEnumerator> >(methods[i], component); } else { targetState.HasEnterRoutine = false; targetState.EnterCall = CreateDelegate <Action>(methods[i], component); } break; case "Exit": if (methods[i].ReturnType == typeof(IEnumerator)) { targetState.HasExitRoutine = true; targetState.ExitRoutine = CreateDelegate <Func <IEnumerator> >(methods[i], component); } else { targetState.HasExitRoutine = false; targetState.ExitCall = CreateDelegate <Action>(methods[i], component); } break; case "Finally": targetState.Finally = CreateDelegate <Action>(methods[i], component); break; case "Update": targetState.Update = CreateDelegate <Action>(methods[i], component); break; case "LateUpdate": targetState.LateUpdate = CreateDelegate <Action>(methods[i], component); break; case "FixedUpdate": targetState.FixedUpdate = CreateDelegate <Action>(methods[i], component); break; case "OnCollisionEnter": targetState.OnCollisionEnter = CreateDelegate <Action <Collision> >(methods[i], component); break; } } currentState = new StateMapping(null); }
public void ChangeState(T newState, MonoFSMStateTransitionOption transition) { if (stateLookup == null) { throw new Exception("没有配置状态机的状态,请调用Init方法进行初始化"); } if (!stateLookup.ContainsKey(newState)) { throw new Exception("没有定义<<" + newState.ToString() + ">>这个状态"); } var nextState = stateLookup[newState]; if (currentState == nextState) { return; } if (queuedChange != null) { engine.StopCoroutine(queuedChange); queuedChange = null; } switch (transition) { case MonoFSMStateTransitionOption.Safe: if (isInTransition) { if (exitRoutine != null) { destinationState = nextState; return; } if (enterRoutine != null) { queuedChange = WaitForPreviousTransition(nextState); engine.StartCoroutine(queuedChange); return; } } break; case MonoFSMStateTransitionOption.Overwrite: if (currentTransition != null) { engine.StopCoroutine(currentTransition); } if (exitRoutine != null) { engine.StopCoroutine(exitRoutine); } if (enterRoutine != null) { engine.StopCoroutine(enterRoutine); } break; } if ((currentState != null && currentState.HasExitRoutine) || nextState.HasEnterRoutine) { isInTransition = true; currentTransition = ChangeToNewStateRoutine(nextState, transition); engine.StartCoroutine(currentTransition); } else { if (currentState != null) { currentState.ExitCall(); currentState.Finally(); } lastState = currentState; currentState = nextState; if (currentState != null) { currentState.EnterCall(); if (OnFSMStateChangedEventHandler != null) { OnFSMStateChangedEventHandler((T)currentState.state); } } isInTransition = false; } }