143 lines
3.7 KiB
C#
143 lines
3.7 KiB
C#
using UnityEngine;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
|
|
public class SimpleStateMachine : MonoBehaviour
|
|
{
|
|
public bool DebugGui;
|
|
public Vector2 DebugGuiPosition;
|
|
|
|
public string DebugGuiTitle = "Simple Machine";
|
|
|
|
protected Enum queueCommand;
|
|
|
|
void OnGUI()
|
|
{
|
|
if (DebugGui)
|
|
{
|
|
GUI.Box(new Rect(DebugGuiPosition.x, DebugGuiPosition.y, 200, 50), DebugGuiTitle);
|
|
|
|
GUI.TextField(new Rect(DebugGuiPosition.x + 10, DebugGuiPosition.y + 20, 180, 20), string.Format("State: {0}", currentState));
|
|
}
|
|
}
|
|
|
|
protected float timeEnteredState;
|
|
|
|
public class State
|
|
{
|
|
public Action DoUpdate = DoNothing;
|
|
public Action DoFixedUpdate = DoNothing;
|
|
public Action DoLateUpdate = DoNothing;
|
|
public Action DoManualUpdate = DoNothing;
|
|
public Action enterState = DoNothing;
|
|
public Action exitState = DoNothing;
|
|
|
|
public Enum currentState;
|
|
}
|
|
|
|
public State state = new State();
|
|
|
|
public Enum currentState
|
|
{
|
|
get
|
|
{
|
|
return state.currentState;
|
|
}
|
|
set
|
|
{
|
|
if(state.currentState == value)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ChangingState();
|
|
state.currentState = value;
|
|
ConfigureCurrentState();
|
|
}
|
|
}
|
|
|
|
[HideInInspector]
|
|
public Enum lastState;
|
|
|
|
void ChangingState()
|
|
{
|
|
lastState = state.currentState;
|
|
timeEnteredState = Time.time;
|
|
}
|
|
|
|
void ConfigureCurrentState()
|
|
{
|
|
if (state.exitState != null)
|
|
{
|
|
state.exitState();
|
|
}
|
|
|
|
//Now we need to configure all of the methods
|
|
state.DoUpdate = ConfigureDelegate<Action>("Update", DoNothing);
|
|
state.DoFixedUpdate = ConfigureDelegate<Action>("FixedUpdate", DoNothing);
|
|
state.DoLateUpdate = ConfigureDelegate<Action>("LateUpdate", DoNothing);
|
|
state.DoManualUpdate = ConfigureDelegate<Action>("ManualUpdate", DoNothing);
|
|
state.enterState = ConfigureDelegate<Action>("EnterState", DoNothing);
|
|
state.exitState = ConfigureDelegate<Action>("ExitState", DoNothing);
|
|
|
|
if (state.enterState != null)
|
|
{
|
|
state.enterState();
|
|
}
|
|
}
|
|
|
|
Dictionary<Enum, Dictionary<string, Delegate>> _cache = new Dictionary<Enum, Dictionary<string, Delegate>>();
|
|
|
|
T ConfigureDelegate<T>(string methodRoot, T Default) where T : class
|
|
{
|
|
|
|
Dictionary<string, Delegate> lookup;
|
|
if(!_cache.TryGetValue(state.currentState, out lookup))
|
|
{
|
|
_cache[state.currentState] = lookup = new Dictionary<string, Delegate>();
|
|
}
|
|
Delegate returnValue;
|
|
if (!lookup.TryGetValue(methodRoot, out returnValue))
|
|
{
|
|
var mtd = GetType().GetMethod(state.currentState.ToString() + "_" + methodRoot, System.Reflection.BindingFlags.Instance
|
|
| System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.InvokeMethod);
|
|
|
|
if(mtd != null)
|
|
{
|
|
returnValue = Delegate.CreateDelegate(typeof(T), this, mtd);
|
|
}
|
|
else
|
|
{
|
|
returnValue = Default as Delegate;
|
|
}
|
|
lookup[methodRoot] = returnValue;
|
|
}
|
|
return returnValue as T;
|
|
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
EarlyGlobalSuperUpdate();
|
|
|
|
state.DoUpdate();
|
|
|
|
LateGlobalSuperUpdate();
|
|
}
|
|
|
|
void FixedUpdate()
|
|
{
|
|
state.DoFixedUpdate();
|
|
}
|
|
|
|
void LateUpdate()
|
|
{
|
|
state.DoLateUpdate();
|
|
}
|
|
|
|
protected virtual void EarlyGlobalSuperUpdate() { }
|
|
|
|
protected virtual void LateGlobalSuperUpdate() { }
|
|
|
|
static void DoNothing() { }
|
|
} |