public void ConstructWithTransitionSucceededEqualToFalse()
		{
			// Act
			var transition = new FiniteStateTransition(1, "TEST", new FiniteStateMachineTransitionReason("0", "BLARG"), this.openState);

			// Assert
			Assert.That(transition.TransitionSucceeded.IsFalse());
		}
Example #2
0
        public void ConstructWithTransitionSucceededEqualToFalse()
        {
            // Act
            var transition = new FiniteStateTransition(1, "TEST", new FiniteStateMachineTransitionReason("0", "BLARG"), this.openState);

            // Assert
            Assert.That(transition.TransitionSucceeded.IsFalse());
        }
Example #3
0
        /// <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;
        }
Example #7
0
        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);
            }
        }
Example #8
0
 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();
        }
Example #11
0
 protected void RemoveTransation(FiniteStateTransition transition)
 {
     allTransitions_.Remove(transition);
 }
Example #12
0
 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;
            }
        }