Guest User

Unity string based state machine

a guest
Oct 22nd, 2014
179
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4.  
  5. public class StateTester : MonoBehaviour {
  6.  
  7.     protected virtual void Start(){
  8.         InitStateSystem();
  9.     }
  10.  
  11.     protected virtual void Update(){
  12.         _activeState.Update();
  13.     }
  14.  
  15.     #region State machine
  16.  
  17.     Dictionary<string, State> states; //we use this to link states to strings
  18.     public string activeState {
  19.         get; //other scripts can read our state string
  20.         private set; //but not change it (which is what SetState() is for)
  21.         //you could change this to set { SetState(value); } but I prefer not to
  22.     }
  23.     State _activeState;
  24.    
  25.     public const string STATE_A = "State A"; //we use constants for this largely to simply code
  26.     public const string STATE_B = "State B"; //if we use the constants to set/change states, we don't have to worry about typos
  27.  
  28.     //this fills our dictionary, linking the strings to the local state class instances
  29.     protected virtual void InitStateSystem(){
  30.         //populate the dictionary with all our states
  31.         states = new Dictionary<string, State>();
  32.         states.Add(STATE_A, stateA);
  33.         states.Add(STATE_B, stateB);
  34.  
  35.         //initialise our states
  36.         stateA.Init(this);
  37.         stateB.Init(this);
  38.  
  39.         //set initial state
  40.         _activeState = stateA;
  41.         activeState = STATE_A;
  42.     }
  43.  
  44.     public virtual void SetState(string nextState){
  45.         if(activeState == nextState) return; //abort if the state we're changing to is the same one we're running anyway
  46.  
  47.         State s;
  48.         //try to find the string nextState in the dictionary, which also sets s if we find one
  49.         if(!states.TryGetValue(nextState, out s)){
  50.             //we could not find a state with that string in the dictionary, so early out without changing anything
  51.             Debug.LogError("Unsupported state " + nextState + "!");
  52.             return;
  53.         }
  54.  
  55.         s.StartState();
  56.         _activeState = s;
  57.         activeState = nextState;
  58.     }
  59.  
  60.     //this is the abstracted form of a state class
  61.     public abstract class State {
  62.         //common state parameters here
  63.         protected StateTester owner; //this is what the state is controlling
  64.  
  65.         //add links to properties in the owner we want to easily read / edit, for example our Transform
  66.         protected Transform transform { get { return owner.transform; } }
  67.  
  68.         //essentially the State's 'Start' function, but you have to call this manually
  69.         public virtual void Init(StateTester a){
  70.             owner = a;
  71.         }
  72.  
  73.         //or whatever function every state is expected to have and be used for
  74.         public abstract void Update();
  75.  
  76.         public abstract void StartState();
  77.  
  78.     }
  79.  
  80.     #endregion
  81.  
  82.     #region State A
  83.    
  84.     //this is our local instance of StateA, which will show up in the inspector
  85.     public StateA stateA;
  86.  
  87.     [System.Serializable] //this tells Unity to save instances of this class
  88.     public class StateA : State {
  89.  
  90.         //properties unique to State A here
  91.         public float spinSpeed = 3;
  92.  
  93.         public override void StartState () {
  94.             Debug.Log("I'm state A! See me spin!");
  95.         }
  96.  
  97.         public override void Update () {
  98.             transform.Rotate(0, Time.deltaTime * spinSpeed, 0);
  99.         }
  100.  
  101.     }
  102.  
  103.     #endregion
  104.  
  105.     #region State B
  106.  
  107.     //this is our local instance of StateB, which will show up in the inspector
  108.     public StateB stateB;
  109.  
  110.     [System.Serializable] //this tells Unity to save instances of this class
  111.     public class StateB : State {
  112.        
  113.         //properties unique to State B here
  114.         public float flySpeed = 4;
  115.        
  116.         public override void StartState () {
  117.             Debug.Log("I'm state B! TO THE MOOOOON!");
  118.         }
  119.        
  120.         public override void Update () {
  121.             transform.Translate(0, Time.deltaTime * flySpeed, 0);
  122.         }
  123.     }
  124.  
  125.     #endregion
  126. }
RAW Paste Data