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() { }
 | 
						|
} |