Hey all,
Terrific course thus far! I’ve never attempted to code any StateMachine/StatePattern/FiniteStateMachine… (at least that I’m aware of… hehe)… so, without further ado!
My little thing I created after watching the lecture
Interfaces
public interface IState
{
void Grounded(IStateContext context);
void Jump(IStateContext context);
void Fall(IStateContext context);
void Land(IStateContext context);
void Crouch(IStateContext context);
}
public interface IStateContext
{
void SetState(IState newState);
}
StateBehaviour
using UnityEngine;
public class StateBehaviour : MonoBehaviour, IStateContext
{
[SerializeField] LocomotionState currentState;
public void Crouch() => currentState.Crouch(this);
public void Fall() => currentState.Fall(this);
public void Jump() => currentState.Jump(this);
public void Land() => currentState.Land(this);
void IStateContext.SetState(IState newState) => currentState = newState as LocomotionState;
void Update()
{
if (Input.GetKeyDown(KeyCode.Q)) Crouch();
if (Input.GetKeyDown(KeyCode.W)) Fall();
if (Input.GetKeyDown(KeyCode.E)) Jump();
if (Input.GetKeyDown(KeyCode.R)) Land();
}
}
States Information
using UnityEngine;
public class LocomotionState : ScriptableObject, IState
{
[SerializeField] protected LocomotionState[] states;
public virtual void Grounded(IStateContext context){}
public virtual void Jump(IStateContext context){}
public virtual void Fall(IStateContext context){}
public virtual void Land(IStateContext context){}
public virtual void Crouch(IStateContext context){}
}
Overriding!
using UnityEngine;
[CreateAssetMenu(fileName = "Grounded LocomotionState", menuName = "Locomotion/New Grounded LocomotionState")]
public class GroundedState : LocomotionState
{
public override void Crouch(IStateContext context)
{
context.SetState(states[0]); // <- Grounded
}
public override void Fall(IStateContext context)
{
context.SetState(states[1]); // <- InAir
}
public override void Jump(IStateContext context)
{
context.SetState(states[1]); // <- InAir
}
}
using UnityEngine;
[CreateAssetMenu(fileName = "Crouch LocomotionState", menuName = "Locomotion/New Crouch LocomotionState")]
public class CrouchState : LocomotionState
{
public override void Crouch(IStateContext context)
{
context.SetState(states[0]); // <- Grounded
}
public override void Fall(IStateContext context)
{
context.SetState(states[1]); // <- InAir
}
public override void Jump(IStateContext context)
{
context.SetState(states[1]); // <- InAir
}
}
using UnityEngine;
[CreateAssetMenu(fileName = "InAir LocomotionState", menuName = "Locomotion/New InAir LocomotionState")]
public class InAirState : LocomotionState
{
public override void Land(IStateContext context)
{
context.SetState(states[0]); // <- Grounded
}
}
Key Differences:
Rather than spawning new instances of each different State script, I just made my States ScriptableObjects.
Another take away is that the main ‘LocomotionState’ class that each State is inheriting has virtual members so they can be overriden to do unique things inside when they themselves are called. I guess it means there’s some flexibility… not all Land calls will do the same thing… depending on the additional code within those State override methods…
Lastly the States themselves have children states within an array that get set when overriding.
Anyways, awesome course!