Skip to content

Instantly share code, notes, and snippets.

@dresswithpockets
Last active April 3, 2022 21:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dresswithpockets/8d87ec94829d0f4dd507dce644dd5d75 to your computer and use it in GitHub Desktop.
Save dresswithpockets/8d87ec94829d0f4dd507dce644dd5d75 to your computer and use it in GitHub Desktop.
public class BetterSimpleStateMachine<TEnum> : Component, IUpdatable
where TEnum : struct, IComparable, IFormattable
{
class StateMethodCache
{
public Action EnterState;
public Func<TEnum> Tick;
public Action ExitState;
}
protected float elapsedTimeInState = 0f;
protected TEnum previousState;
Dictionary<TEnum, StateMethodCache> _stateCache;
StateMethodCache _stateMethods;
TEnum _currentState;
public TEnum CurrentState
{
get => _currentState;
set
{
// dont change to the current state
if (_stateCache.Comparer.Equals(_currentState, value))
return;
// swap previous/current
previousState = _currentState;
_currentState = value;
// exit the state, fetch the next cached state methods then enter that state
if (_stateMethods.ExitState != null)
_stateMethods.ExitState();
elapsedTimeInState = 0f;
_stateMethods = _stateCache[_currentState];
if (_stateMethods.EnterState != null)
_stateMethods.EnterState();
}
}
public TEnum InitialState
{
set
{
_currentState = value;
_stateMethods = _stateCache[_currentState];
if (_stateMethods.EnterState != null)
_stateMethods.EnterState();
}
}
public BetterSimpleStateMachine(IEqualityComparer<TEnum> customComparer = null)
{
_stateCache = new Dictionary<TEnum, StateMethodCache>(customComparer);
// cache all of our state methods
var enumValues = (TEnum[]) Enum.GetValues(typeof(TEnum));
}
public virtual void Update()
{
elapsedTimeInState += Time.DeltaTime;
if (_stateMethods.Tick != null)
CurrentState = _stateMethods.Tick();
}
public void AddCallbacks(TEnum stateEnum, Action enterState, Func<TEnum> tick, Action exitState)
{
var state = new StateMethodCache
{
EnterState = enterState,
Tick = tick,
ExitState = exitState,
};
_stateCache[stateEnum] = state;
}
}
enum MoveState {
Normal,
Dashing,
}
class Player {
// ...
MoveState NormalUpdate() {
if (ShouldDash && TryDash()) {
return MoveState.Dashing;
}
// do normal movement stuff
}
bool TryDash() {
// do some preliminary logic to see if they can dash
return canDash;
}
void EnterDash() {
// begin dashing
}
MoveState Dashing() {
// update loop or dashing state
if (DashOver) {
return MoveState.Normal;
}
}
void ExitDash() {
// after dash is over
}
// ...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment