Skip to content

Instantly share code, notes, and snippets.

@FNGgames
Created September 22, 2018 13:09
Show Gist options
  • Save FNGgames/111bd76646b4497453e2f8ef98124c76 to your computer and use it in GitHub Desktop.
Save FNGgames/111bd76646b4497453e2f8ef98124c76 to your computer and use it in GitHub Desktop.
Generic Finite State Machine
public class FiniteStateMachine<T_Data, T_Id>
{
protected T_Data data;
protected FSMState<T_Data, T_Id> globalState;
protected FSMState<T_Data, T_Id> activeState;
protected Dictionary<T_Id, FSMState<T_Data, T_Id>> states;
public FiniteStateMachine(T_Data data)
{
this.data = data;
states = new Dictionary<T_Id, FSMState<T_Data, T_Id>>();
}
public virtual void SetGlobalState(FSMState<T_Data, T_Id> state)
{
globalState = state;
}
public virtual void AddState(FSMState<T_Data, T_Id> state)
{
if (states.ContainsKey(state.id))
throw new Exception("State machine already contains state with id {0}", state.id);
states.Add(state.id, state);
if (activeState == null) TransitionToState(state.id);
}
public virtual void RemoveState(FSMState<T_Data, T_Id> state)
{
if (states.ContainsKey(state.id)) states.Remove(state.id);
}
public virtual void Update()
{
if (globalState != null) globalState.OnUpdate(data);
if (activeState != null) activeState.OnUpdate(data);
}
public virtual void TransitionToState(T_Id id)
{
if (!states.ContainsKey(id)) return;
var targetState = states[id];
if (activeState != null)
{
activeState.TransitionEvent -= TransitionToState;
activeState.OnExit(data);
}
activeState = targetState;
activeState.TransitionEvent += TransitionToState;
activeState.OnEnter(data);
}
}
public abstract class FSMState<T_Data, T_Id>
{
public abstract T_Id id { get; protected set; }
public virtual void OnEnter(T_Data data) { }
public virtual void OnUpdate(T_Data data) { }
public virtual void OnExit(T_Data data) { }
public delegate void TransitionEventHandler(T_Id id);
public event TransitionEventHandler TransitionEvent;
protected virtual void FireTransition(T_Id targetId)
{
if (TransitionEvent != null) TransitionEvent(targetId);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment