Last active
August 21, 2022 15:15
-
-
Save FlaShG/2ee7a3fd82b9068f3f76defc2c4d503c to your computer and use it in GitHub Desktop.
A simple state machine class for Unity. Use it to run regular methods or coroutines as states.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System; | |
using System.Collections; | |
/// <summary> | |
/// A simple state machine class. Use it to run regular methods or coroutines as states. | |
/// Steps to use: | |
/// 1. Define a private field for the StateMachine object. | |
/// private StateMachine stateMachine; | |
/// 2. Initialize the object in Awake. Pass the MonoBehaviour object to the constructor. | |
/// stateMachine = new StateMachine(this); | |
/// 3. Use SetNextState to pass either a void method or a coroutine as a state to the statemachine. | |
/// The state will run in a loop until SetNextSate is called. | |
/// The current state will come to an end, and the next state will be started in a loop afterwards. | |
/// </summary> | |
public class StateMachine | |
{ | |
private MonoBehaviour owner; | |
private Action nextState; | |
private Func<IEnumerator> nextCState; | |
private bool nextStateIsCoroutine; | |
private bool running = false; | |
public bool isInThisState { get; private set; } | |
#region Constructors | |
public StateMachine(MonoBehaviour owner) | |
{ | |
if (!owner) | |
{ | |
throw new ArgumentException("You need to assign a MonoBehaviour to this StateMachine!"); | |
} | |
this.owner = owner; | |
} | |
#endregion | |
#region State Setters and Helper Methods | |
public void SetNextState(Action state) | |
{ | |
nextState = state; | |
nextCState = null; | |
nextStateIsCoroutine = false; | |
StateSet(); | |
} | |
public void SetNextState(Func<IEnumerator> state) | |
{ | |
nextCState = state; | |
nextState = null; | |
nextStateIsCoroutine = true; | |
StateSet(); | |
} | |
private void StateSet() | |
{ | |
isInThisState = false; | |
if (!running && HasNextState()) | |
{ | |
owner.StartCoroutine(Run()); | |
} | |
} | |
private bool HasNextState() | |
{ | |
return nextStateIsCoroutine ? (nextCState != null) : (nextState != null); | |
} | |
#endregion | |
private IEnumerator Run() | |
{ | |
running = true; | |
while (HasNextState()) | |
{ | |
if (!owner) | |
{ | |
Debug.LogError("The MonoBehaviour assigned to this StateMachine has been destroyed!"); | |
running = false; | |
yield break; | |
} | |
isInThisState = true; | |
if (nextStateIsCoroutine) | |
{ | |
yield return owner.StartCoroutine(nextCState()); | |
} | |
else | |
{ | |
nextState(); | |
yield return null; | |
} | |
} | |
running = false; | |
isInThisState = false; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
/// <summary> | |
/// Example class for StateMachine.cs. | |
/// When in the idle state, pressing space triggers the fly state, which lasts for two seconds before returning to the idle state. | |
/// </summary> | |
public class StateMachineDemo : MonoBehaviour | |
{ | |
private StateMachine stateMachine; | |
private void Awake() | |
{ | |
stateMachine = new StateMachine(this); | |
} | |
private void Start() | |
{ | |
stateMachine.SetNextState(IdleState); | |
} | |
private void IdleState() | |
{ | |
if(Input.GetKeyDown(KeyCode.Space)) | |
{ | |
stateMachine.SetNextState(FlyState); | |
} | |
} | |
private IEnumerator FlyState() | |
{ | |
// TODO Start upwards Movement | |
yield return new WaitForSeconds(2); | |
// TODO Stop upwards movement | |
stateMachine.SetNextState(IdleState); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment