コード例 #1
0
    private IEnumerator ChangeToNewStateRoutine(StateMapping newState, StateTransition 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 != StateTransition.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;
    }
コード例 #2
0
    private IEnumerator ChangeToNewStateRoutine(StateMapping newState, StateTransition transtiion)
    {
        _destinationState = newState;

        if (_currentState != null)
        {
            if (_currentState.hasExitRoutine)
            {
                _exitRoutine = _currentState.ExitRoutine();

                if (_exitRoutine != null && transtiion != StateTransition.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 (Changed != null)
            {
                Changed(_currentState.State);
            }
        }

        _isInTransition = false;
    }
コード例 #3
0
    public void ChangeState(T newState, StateTransition 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 StateTransition.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 StateTransition.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;
        }
    }