using System; namespace OM { /// /// Interface for a state in a state machine. /// /// public interface IOMState { /// /// called when the state is about to be entered from another state to check if the state can be entered. /// /// /// bool CanEnterState(T fromState) => true; /// /// called when the state is entered from another state. /// /// void OnEnterState(T fromState); /// /// called when the state is about to be exited to check if the state can be exited. /// /// /// bool CanExitState(T toState) => true; /// /// called when the state is exited to another state. /// /// void OnExitState(T toState); /// /// called every frame to update the state if the state is active. /// void OnUpdateState() { } } /// /// A state machine that can be used to manage states in a generic way. /// /// public class OMStateMachine where T : IOMState { /// /// event that is called when the state is changed. /// public event Action OnStateChanged; /// /// Last state before the current state. /// public T LastState { get; private set; } /// /// Current state of the state machine. /// public T CurrentState { get; private set; } /// /// Constructor for the state machine. /// /// /// public OMStateMachine(T initState,Action onStateChanged = null) { SetNewState(initState); if(onStateChanged != null) OnStateChanged += onStateChanged; } /// /// Sets a new state for the state machine and invokes the state changed event if the state has changed. /// /// /// /// public bool SetNewState(T newState,bool force = false) { if(newState == null) return false; if (!force) { if (!newState.CanEnterState(fromState:CurrentState)) return false; if (CurrentState != null && !CurrentState.CanExitState(toState:newState)) return false; } CurrentState?.OnExitState(toState:newState); LastState = CurrentState; CurrentState = newState; CurrentState?.OnEnterState(fromState:LastState); OnStateChanged?.Invoke(CurrentState,LastState); return true; } /// /// Updates the current state by calling the OnUpdateState method of the current state. /// public void UpdateStateMachine() { CurrentState?.OnUpdateState(); } /// /// Subscribes to the state changed event. /// /// public void OnChange(Action callback) { OnStateChanged += callback; } } }