public void ConstructWithTransitionSucceededEqualToFalse() { // Act var transition = new FiniteStateTransition(1, "TEST", new FiniteStateMachineTransitionReason("0", "BLARG"), this.openState); // Assert Assert.That(transition.TransitionSucceeded.IsFalse()); }
public void ConstructWithTransitionSucceededEqualToFalse() { // Act var transition = new FiniteStateTransition(1, "TEST", new FiniteStateMachineTransitionReason("0", "BLARG"), this.openState); // Assert Assert.That(transition.TransitionSucceeded.IsFalse()); }
/// <summary> /// Add transition /// </summary> /// <param name="eventName">Event name.</param> /// <typeparam name="T1">src state type.</typeparam> /// <typeparam name="T2">desk state type.</typeparam> protected void AddTransition <T1, T2>(string eventName) where T1 : FiniteState where T2 : FiniteState { string lastStateName = typeof(T1).Name; string nextStateName = typeof(T2).Name; FiniteStateTransition transition = new FiniteStateTransition(eventName, lastStateName, nextStateName); allTransitions_.Add(transition); }
public static void CopySerializedField(SerializedProperty property, FiniteStateTransition trans) { var prop = property.FindPropertyRelative("m_ConditionMethod"); trans.m_ConditionMethod = prop.stringValue; prop = property.FindPropertyRelative("m_FromState"); trans.m_FromState = prop.stringValue; prop = property.FindPropertyRelative("m_ToState"); trans.m_ToState = prop.stringValue; }
public static void CopyTransitionToSerializedField(FiniteStateTransition trans, SerializedProperty property) { var prop = property.FindPropertyRelative("m_ConditionMethod"); prop.stringValue = trans.m_ConditionMethod; prop = property.FindPropertyRelative("m_FromState"); prop.stringValue = trans.m_FromState; prop = property.FindPropertyRelative("m_ToState"); prop.stringValue = trans.m_ToState; }
private IEnumerator ChangeToNewStateRoutine(FiniteStateMapping newState, FiniteStateTransition transition) { destinationState = newState; //Chache this so that we can overwrite it and hijack a transition if (currentState != null) { if (currentState.hasExitRoutine) { exitRoutine = currentState.ExitRoutine(); if (exitRoutine != null && transition != FiniteStateTransition.Overwrite) //Don't wait for exit if we are overwriting { 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(); } //Broadcast change only after enter transition has begun. if (Changed != null) { Changed((T)currentState.state); } } isInTransition = false; }
protected void AddAnyTransition <T>(string eventName) where T : FiniteState { string nextStateName = typeof(T).Name; foreach (var state in allStates_) { string lastStateName = state.Value.GetType().Name; FiniteStateTransition transition = new FiniteStateTransition(eventName, lastStateName, nextStateName); allTransitions_.Add(transition); } }
private bool TryGetNextStateByEventName( FiniteStateTransition transition, string eventName, out FiniteState state) { state = null; if (CurrentState == null || !CurrentState.Name.Equals(transition.LastStateName)) { return(false); } if (!eventName.Equals(transition.EventName)) { return(false); } return(allStates_.TryGetValue(transition.NextStateName, out state)); }
private static void GenerateTransitions(SerializedObject target, Type type) { var fsm = target.targetObject as FStateMachineMono; var prop = target.FindProperty("m_Transitions"); object[] methods = Ref.GetMethodsWithAttribute <FStateTransitionAttribute>(type, true); if (methods == null) { prop.ClearArray(); return; } List <FiniteStateTransition> transitions = new List <FiniteStateTransition>(); for (int i = 0; i < methods.Length; i++) { System.Reflection.MethodInfo mtd = methods[i] as System.Reflection.MethodInfo; if (!Ref.MatchMethodRetAndParams(mtd, typeof(bool), null)) { RTLog.LogError(LogCat.AI, string.Format("{0} 不能作为状态方法,因为类型不能和 \" bool Method() \" 匹配.", mtd.Name)); continue; } object[] trans = mtd.GetCustomAttributes(typeof(FStateTransitionAttribute), true); for (int j = 0; j < trans.Length; j++) { FStateTransitionAttribute t = trans[j] as FStateTransitionAttribute; FiniteStateTransition ft = new FiniteStateTransition(); ft.m_FromState = t.From ?? ""; //if (!string.IsNullOrEmpty(ft.m_FromState) && !fsm.HasState(ft.m_FromState)) // continue; ft.m_ToState = t.To ?? ""; //if (!string.IsNullOrEmpty(ft.m_ToState) && !fsm.HasState(ft.m_ToState)) // continue; ft.m_ConditionMethod = mtd.Name ?? ""; transitions.Add(ft); } } GlobalUtil.Sort(transitions, (x, y) => string.IsNullOrEmpty(x.m_FromState) || string.IsNullOrEmpty(x.m_ToState) ? 1 : -1); prop.arraySize = transitions.Count; for (int i = 0; i < transitions.Count; i++) { var p = prop.GetArrayElementAtIndex(i); CopyTransitionToSerializedField(transitions[i], p); } }
void GetCopys() { m_StateCopys = new FiniteState[m_States.arraySize]; for (int i = 0; i < m_StateCopys.Length; i++) { m_StateCopys[i] = new FiniteState(); CopySerializedField(m_States.GetArrayElementAtIndex(i), m_StateCopys[i]); } m_TransitionCopys = new FiniteStateTransition[m_Transitions.arraySize]; for (int i = 0; i < m_TransitionCopys.Length; i++) { m_TransitionCopys[i] = new FiniteStateTransition(); CopySerializedField(m_Transitions.GetArrayElementAtIndex(i), m_TransitionCopys[i]); } m_TransArrows.Clear(); HashSet <int> execlude = new HashSet <int>(); for (int i = 0; i < m_TransitionCopys.Length; i++) { if (execlude.Contains(i)) { continue; } var arrow = new Arrow(); var trans = m_TransitionCopys[i]; arrow.from = GlobalUtil.FindIndex(m_StateCopys, (x) => x.m_StateName == trans.m_FromState); arrow.to = GlobalUtil.FindIndex(m_StateCopys, (x) => x.m_StateName == trans.m_ToState); var reverse = arrow.from == -1 || arrow.to == -1 ? -1 : GlobalUtil.FindIndex(m_TransitionCopys, (x) => x.m_FromState == trans.m_ToState && x.m_ToState == trans.m_FromState); if (reverse != -1) { execlude.Add(reverse); arrow.twoSide = true; } m_TransArrows.Add(arrow); } Reposition(); }
protected void RemoveTransation(FiniteStateTransition transition) { allTransitions_.Remove(transition); }
protected void AddTransition(FiniteStateTransition transition) { allTransitions_.Add(transition); }
void DrawStateInfo() { if (interceptedState != -1) { Rect rect; Vector2 pos = interaceptPos; //pos -= stateViewPos - stateClipRectCenter; rect = new Rect(pos, new Vector2(stateClipRect.width - 20, stateClipRect.height - 20)); GUI.skin.label.richText = true; FiniteState state = fsm.States[interceptedState]; strbuffer.Remove(0, strbuffer.Length); strbuffer.Append("State: ").Append(state.m_StateName).Append('\n'); strbuffer.Append("Keep In Stack: ").Append(state.m_KeepInStack).Append('\n'); if (!string.IsNullOrEmpty(state.m_BeginMethod)) { strbuffer.Append('\n').Append("OnBegin: void "); strbuffer.Append(fsm.Implement.GetType().Name).Append('.').Append(state.m_BeginMethod).Append(" ()"); } if (!string.IsNullOrEmpty(state.m_TickMethod)) { strbuffer.Append('\n').Append("OnTick: void "); strbuffer.Append(fsm.Implement.GetType().Name).Append('.').Append(state.m_TickMethod).Append(" ()"); } if (!string.IsNullOrEmpty(state.m_EndMethod)) { strbuffer.Append('\n').Append("OnEnd: void "); strbuffer.Append(fsm.Implement.GetType().Name).Append('.').Append(state.m_EndMethod).Append(" ()"); } strbuffer.Append('\n'); for (int i = 0; i < fsm.TransitionLength; i++) { FiniteStateTransition trans = fsm.Transitions[i]; if (trans.m_ToState == state.m_StateName) { strbuffer.Append("\nFrom ") .Append(string.IsNullOrEmpty(trans.m_FromState) ? "[Any]" : trans.m_FromState) .Append(": bool "); strbuffer.Append(fsm.Implement.GetType().Name).Append('.') .Append(trans.m_ConditionMethod).Append(" ()"); } } strbuffer.Append('\n'); for (int i = 0; i < fsm.TransitionLength; i++) { FiniteStateTransition trans = fsm.Transitions[i]; if (trans.m_FromState == state.m_StateName || string.IsNullOrEmpty(trans.m_FromState) && trans.m_ToState != state.m_StateName) { strbuffer.Append("\nTo ") .Append(string.IsNullOrEmpty(trans.m_ToState) ? "[Return]" : trans.m_ToState) .Append(": bool "); strbuffer.Append(fsm.Implement.GetType().Name).Append('.') .Append(trans.m_ConditionMethod).Append(" ()"); } } if (Application.isPlaying) { strbuffer.Append('\n'); strbuffer.Append('\n').Append("Ticks: ").Append(fsmImpl.TotalTicks); strbuffer.Append('\n').Append("Time: ").Append(fsmImpl.TotalRuntime.ToString("0.##")).Append('s'); if (fsmImpl.CurrentStateName == state.m_StateName) { strbuffer.Append('\n').Append("State Ticks: ").Append(fsmImpl.CurrentStateTicks); strbuffer.Append('\n').Append("State Time: ").Append(fsmImpl.CurrentStateTime.ToString("0.##")).Append('s'); } } GUI.Label(rect, strbuffer.ToString(), "window"); } }
void DrawTransition(bool activeTrans) { string current = fsmImpl == null ? null : fsmImpl.CurrentStateName; int currentIndex = GetStateIndex(current); int from, to; Rect fromRect, toRect; for (int i = 0; i < fsm.TransitionLength; i++) { FiniteStateTransition trans = fsm.Transitions[i]; to = GetStateIndex(trans.m_ToState); from = GetStateIndex(trans.m_FromState); if (to == -1 && from == -1) { for (int j = 0; j < stateRects.Length; j++) { if (activeTrans ^ (Application.isPlaying && currentIndex == j)) { continue; } fromRect = stateRects[j]; fromRect.y += fromRect.height; fromRect.x -= (defaultCellSize.x * cellScale * 0.5f - 10); toRect = fromRect; toRect.y -= fromRect.height * 2f; fromRect.position -= stateViewPos - stateClipRectCenter; toRect.position -= stateViewPos - stateClipRectCenter; HandleTransition(fromRect, toRect, activeTrans ? Color.green : Color.red); } } else if (to != -1 && from != -1) { if (activeTrans ^ (Application.isPlaying && currentIndex == from)) { continue; } fromRect = stateRects[from]; toRect = stateRects[to]; fromRect.position -= stateViewPos - stateClipRectCenter; toRect.position -= stateViewPos - stateClipRectCenter; HandleTransition(fromRect, toRect, activeTrans ? Color.green : Color.red); } else { int p = from != -1 ? from : to; if (activeTrans ^ (Application.isPlaying && (currentIndex == from || from == -1))) { continue; } float sign = p == from ? -1 : 1; fromRect = stateRects[p]; fromRect.y -= fromRect.height * sign; fromRect.x += (defaultCellSize.x * cellScale * 0.5f - 10) * sign; toRect = fromRect; toRect.y += fromRect.height * 2f * sign; fromRect.position -= stateViewPos - stateClipRectCenter; toRect.position -= stateViewPos - stateClipRectCenter; HandleTransition(fromRect, toRect, activeTrans ? Color.green : Color.red); } } }
public void ChangeState(T newState, FiniteStateTransition transition) { if (stateLookup == null) { throw new Exception("States have not been configured, please call initialized before trying to set state"); } if (!stateLookup.ContainsKey(newState)) { throw new Exception("No state with the name " + newState.ToString() + " can be found. Please make sure you are called the correct type the statemachine was initialized with"); } var nextState = stateLookup[newState]; if (currentState == nextState) { return; } //Cancel any queued changes. if (queuedChange != null) { engine.StopCoroutine(queuedChange); queuedChange = null; } switch (transition) { //case StateMachineTransition.Blend: //Do nothing - allows the state transitions to overlap each other. This is a dumb idea, as previous state might trigger new changes. //A better way would be to start the two couroutines at the same time. IE don't wait for exit before starting start. //How does this work in terms of overwrite? //Is there a way to make this safe, I don't think so? //break; case FiniteStateTransition.Safe: if (isInTransition) { if (exitRoutine != null) //We are already exiting current state on our way to our previous target state { //Overwrite with our new target destinationState = nextState; return; } if (enterRoutine != null) //We are already entering our previous target state. Need to wait for that to finish and call the exit routine. { //Damn, I need to test this hard queuedChange = WaitForPreviousTransition(nextState); engine.StartCoroutine(queuedChange); return; } } break; case FiniteStateTransition.Overwrite: if (currentTransition != null) { engine.StopCoroutine(currentTransition); } if (exitRoutine != null) { engine.StopCoroutine(exitRoutine); } if (enterRoutine != null) { engine.StopCoroutine(enterRoutine); } //Note: if we are currently in an EnterRoutine and Exit is also a routine, this will be skipped in ChangeToNewStateRoutine() break; } if ((currentState != null && currentState.hasExitRoutine) || nextState.hasEnterRoutine) { isInTransition = true; currentTransition = ChangeToNewStateRoutine(nextState, transition); engine.StartCoroutine(currentTransition); } else //Same frame transition, no coroutines are present { if (currentState != null) { currentState.ExitCall(); currentState.Finally(); } lastState = currentState; currentState = nextState; if (currentState != null) { currentState.EnterCall(); if (Changed != null) { Changed((T)currentState.state); } } isInTransition = false; } }