Advertisement
Guest User

C# State Machine

a guest
Jun 27th, 2019
282
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 2.78 KB | None | 0 0
  1. public class StateMachine<S, T> : MonoBehaviour
  2. {
  3.     protected State<S, T> _currentState;
  4.     protected List<IStateMachineSubscriber> _stateMachineSubscribers = new List<IStateMachineSubscriber>();
  5.     protected Queue<T> _commands = new Queue<T>();
  6.  
  7.     private T _activeCommand;
  8.  
  9.     //TODO: probably make 'em protected
  10.     public State<S, T> _initState;
  11.     public AbstractStateFactory<S, T> _stateFactory;
  12.  
  13.     public State<S,T> CurrentState { get { return _currentState; } }
  14.  
  15.     public delegate void StateEnterEventHandler(S state);
  16.     public delegate void StateExitEventHandler(S state);
  17.     public delegate void StateChangeEventHandler(S prevState, S newState);
  18.  
  19.     public event StateEnterEventHandler OnStateEnter;
  20.     public event StateExitEventHandler OnStateExit;
  21.     public event StateChangeEventHandler OnStateChange;
  22.  
  23.     public virtual void Start()
  24.     {
  25.         Debug.Log("State Machine created!");
  26.     }
  27.  
  28.     public virtual void HandleCommand(T command)
  29.     {
  30.         if (command.Equals(_activeCommand))
  31.         {
  32.             Debug.LogWarning($"Received command {command.ToString()}, but the same command is already ACTIVE");
  33.             return;
  34.         }
  35.  
  36.         if (_commands.Contains(command))
  37.         {
  38.             Debug.LogWarning($"Received command {command.ToString()}, but the same command is already IN QUEUE");
  39.             return;
  40.         }
  41.  
  42.         _commands.Enqueue(command);
  43.         Debug.Log($"Enqueued command: {command.ToString()}");
  44.     }
  45.  
  46.     public virtual void Update()
  47.     {          
  48.         if (_commands.Count > 0)
  49.         {
  50.             var commandCandidate = _commands.Peek();
  51.             if (ProcessCommand(commandCandidate))
  52.             {
  53.                 _commands.Dequeue();
  54.                 Debug.Log($"Dequeued command {commandCandidate.ToString()}");
  55.             }
  56.         }
  57.         else
  58.         {
  59.             _activeCommand = default(T);
  60.         }
  61.     }
  62.  
  63.     public virtual void SubscribeToStateMachine(IStateMachineSubscriber subscriber)
  64.     {
  65.         if (!_stateMachineSubscribers.Contains(subscriber))
  66.         {
  67.             _stateMachineSubscribers.Add(subscriber);
  68.         }
  69.     }
  70.  
  71.     public virtual void UnsubscribeToStateMachine(IStateMachineSubscriber subscriber)
  72.     {
  73.         if (_stateMachineSubscribers.Contains(subscriber))
  74.         {
  75.             _stateMachineSubscribers.Remove(subscriber);
  76.         }
  77.     }
  78.  
  79.     #region Protected methods
  80.     protected bool ProcessCommand(T command)
  81.     {
  82.         foreach (var subscriber in _stateMachineSubscribers)
  83.         {
  84.             while (!subscriber.IsReady)
  85.             {
  86.                 return false;
  87.             }
  88.         }
  89.  
  90.         var newState = _currentState.CheckTransCondition(command);            
  91.  
  92.         if (!_currentState.StateName.Equals(newState))
  93.         {
  94.             _activeCommand = command;
  95.  
  96.             OnStateExit?.Invoke(_currentState.StateName);
  97.  
  98.             var prevState = _currentState;
  99.             _currentState = _stateFactory.CreateState(newState);
  100.  
  101.             OnStateEnter?.Invoke(_currentState.StateName);
  102.  
  103.             OnStateChange?.Invoke(prevState.StateName, _currentState.StateName);
  104.  
  105.             Debug.Log("Switched to " + newState.ToString());
  106.         }
  107.         return true;
  108.     }
  109.     #endregion
  110. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement