Skip to content

Instantly share code, notes, and snippets.

@Danielmelody
Last active August 7, 2016 01:30
Show Gist options
  • Save Danielmelody/42da732e4c5325340c9ba83f28a84575 to your computer and use it in GitHub Desktop.
Save Danielmelody/42da732e4c5325340c9ba83f28a84575 to your computer and use it in GitHub Desktop.
Simple State Machine for Generally Use in C#
// Simple State Machine with clever transition-event management
// created by yiminghu:github.com/Danielhu
using System.Collections.Generic;
public class StateMachine<StateType>{
public delegate void TransitionDelegate();
public StateType current {
get { return currentState; }
}
StateType currentState;
Dictionary<StateType, Dictionary<StateType, TransitionDelegate>> stateChangeEvents;
Dictionary<StateType, TransitionDelegate> onStateEnterEvents;
Dictionary<StateType, TransitionDelegate> onStateLeaveEvents;
Dictionary<StateType, HashSet<StateType>> forbidenTrasitions;
public StateMachine() {
stateChangeEvents = new Dictionary<StateType, Dictionary<StateType, TransitionDelegate>> ();
onStateEnterEvents = new Dictionary<StateType, TransitionDelegate> ();
onStateLeaveEvents = new Dictionary<StateType, TransitionDelegate> ();
forbidenTrasitions = new Dictionary<StateType, HashSet<StateType>> ();
}
public void forbidTrasition(StateType fromState, StateType toState) {
HashSet<StateType> toForbiddenList;
if (!forbidenTrasitions.TryGetValue (fromState, out toForbiddenList)) {
forbidenTrasitions.Add (fromState, new HashSet<StateType>());
}
if (!forbidenTrasitions [fromState].Contains (toState)) {
forbidenTrasitions [fromState].Add (toState);
}
}
public void addOnStateEnterEvent (StateType state, TransitionDelegate onChange) {
if (!onStateEnterEvents.ContainsKey(state)){
onStateEnterEvents.Add (state, onChange);
} else {
onStateEnterEvents [state] += onChange;
}
}
public void addOnStateLeaveEvent (StateType state, TransitionDelegate onChange) {
if (!onStateLeaveEvents.ContainsKey(state)){
onStateLeaveEvents.Add (state, onChange);
} else {
onStateLeaveEvents [state] += onChange;
}
}
public void addOnStateChangeEvent(StateType fromState, StateType toState, TransitionDelegate onChange) {
if (fromState.Equals(toState)) {
Debug.LogWarning ("cannot add change events because from and to events are equal");
return;
}
if (!stateChangeEvents.ContainsKey (fromState)) {
stateChangeEvents.Add (fromState, new Dictionary<StateType, TransitionDelegate> ());
}
if (!stateChangeEvents [currentState].ContainsKey (toState)) {
stateChangeEvents [fromState].Add (toState, onChange);
} else {
stateChangeEvents [fromState] [toState] += onChange;
}
}
public void changeState(StateType state) {
if (state.Equals(currentState)) {
Debug.LogWarning ("state not change");
return;
}
if (forbidenTrasitions.ContainsKey (currentState)) {
if (forbidenTrasitions [currentState].Contains (state)) {
Debug.Log ("transition has been forbidden");
return;
}
}
Dictionary<StateType, TransitionDelegate> fromDict;
if (stateChangeEvents.TryGetValue (currentState, out fromDict)) {
TransitionDelegate trans;
if (stateChangeEvents [currentState].TryGetValue (state, out trans)) {
trans ();
}
}
TransitionDelegate leaveTrans;
if (onStateLeaveEvents.TryGetValue (currentState, out leaveTrans)) {
leaveTrans ();
Debug.LogWarning ("leave trans");
}
TransitionDelegate enterTrans;
if (onStateEnterEvents.TryGetValue (state, out enterTrans)) {
enterTrans ();
}
currentState = state;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment