Skip to content

Repository files navigation

What is it?

This package is a foundation that allows you to easily build an FSM in your Unity project using our building blocks. It features:

  • FSM execution and state transition logic;
  • Overrideable state enter/exit hook methods;
  • State enter/exit UnityEvents;
  • State execution duration;

How to install Finite State Machine in my Unity project?

Use the Unity Package Manager (in Unity’s top menu: Window > Package Manager), click the "+" icon, select "Add package from git URL" and type the URL of this repository:

https://github.com/madeyellow/FiniteStateMachine.git

Installing package via PackageManager

Getting started

Creating an FSM with use of this package is as simple as defining your state base, the states you need, and FSM itself. Like this:

usingMadeYellow.FSM;usingUnityEngine;/// <summary>/// Base for any state in our FSM, refrencing FSM/// </summary>publicabstractclassMyFiniteStateMachineStateBase:StateBase{protectedreadonlyMyFiniteStateMachineFiniteStateMachine;publicMyFiniteStateMachineStateBase(MyFiniteStateMachinefiniteStateMachine){FiniteStateMachine=finiteStateMachine;}}/// <summary>/// Example of some state/// </summary>publicclassMyState:MyFiniteStateMachineStateBase{privatefloat_time;publicMyState(MyFiniteStateMachinefiniteStateMachine):base(finiteStateMachine){}protectedoverridevoidExecuteHandler(infloatdeltaTime){// This is logic of your state. You may implement anything here._time+=deltaTime;Debug.Log($"{_time} has passed");}}/// <summary>/// Your FSM/// </summary>publicclassMyFiniteStateMachine:FiniteStateMachineBase<MyFiniteStateMachineStateBase>{publicreadonlyMyStateSomeState;publicreadonlyMyStateSomeOtherState;publicMyFiniteStateMachine(){SomeState=newMyState(this);SomeOtherState=newMyState(this);ChangeState(SomeState);}}

States define execution logic (e.g. how a character should move, fall, swim, etc.), and FSM gives you the ability to translate between those states. You may use your FSM in some MonoBehaviour like this:

publicclassBasicCharacter:MonoBehaviour{privateMyFiniteStateMachine_fsm;privatevoidAwake(){_fsm=newMyFiniteStateMachine();}privatevoidFixedUpdate(){_fsm.Execute(Time.fixedDeltaTime);}}

Translating from one state to another

If you want to translate from state SomeState to state SomeOtherState you should override the CheckTransitions() method in the MyState class and use the FiniteStateMachine.ChangeState() method like this:

publicoverridevoidCheckTransitions(){// Some condition to transition from this state. CheckTransitions() of CurrentState executes before ExecuteHandler() each time you call Execute() in your FSMif(_time>1){// A way to change state of FSM. FSM will use ExecuteHandler of SomeOtherState instead of this stateFiniteStateMachine.ChangeState(FiniteStateMachine.SomeOtherState);}}

Current & previous states of FSM

If you want to know which state your FSM is now or was in before you may use the CurrentState and the PreviousState properties of your FSM:

publicclassBasicCharacter:MonoBehaviour{privateMyFiniteStateMachine_fsm;privatevoidSomeMethod(){varcurrentState=_fsm.CurrentState;varpreviousState=_fsm.PreviousState;}}

You may even use it inside your state to define various logic based on the previous state:

publicclassMyState:MyFiniteStateMachineStateBase{privatefloat_time;publicMyState(MyFiniteStateMachinefiniteStateMachine):base(finiteStateMachine){}protectedoverridevoidExecuteHandler(infloatdeltaTime){// Execute only if previous state was SomeStateif(FiniteStateMachine.PreviousState==FiniteStateMachine.SomeState){_time+=deltaTime;}Debug.Log($"{_time} has passed");}}

FSM state change event

Each time your FSM changes its state it invokes an OnCurrentStateChanged UnityEvent. This may be useful if you want to perform some action on a change of state for some reason.

publicclassBasicCharacter:MonoBehaviour{privateMyFiniteStateMachine_fsm;privatevoidAwake(){_fsm=newMyFiniteStateMachine();_fsm.OnCurrentStateChanged.AddListener(OnStateChanged);// Subscribes to change of state in _fsm}privatevoidOnStateChanged(){// Some logic}}

Enter/Exit state hook methods

You can add custom logic to your state when FSM enters or exits certain states. This can be useful to fetch & cache some data from FSM (like fetching velocity of character to determine how much damage you should apply on fall damage, etc.) or reset something inside your state before first ExecuteHandler() will be invoked.

There are two methods inside your state for it:

protectedoverridevoidStateEnteringHook(){Debug.Log($"MyState entereted");// This will be called when FSM enter your state}protectedoverridevoidStateExitingHook(){Debug.Log($"MyState exited");// This will be called when FSM exit your state}

State enter/exit events

If you want other components to execute some logic when your FSM enters or exists in some specific state (e.g. show a character's fall animation in the animator when entering "air" state, or showing attack animation when entering "melee attack" state, etc.) you may use the state's OnEnteredState and OnExitedState UnityEvents.

publicclassBasicCharacterAnimator:MonoBehaviour{privateMyFiniteStateMachine_fsm;privatevoidAwake(){_fsm.SomeState.OnEnteredState.AddListener(OnSomeStateEntered);}privatevoidOnSomeStateEntered(){}}

State execution duration

If, for some reason, you'll need to know how long a certain state has been executing since last entering it, you may use the state's ExecutionDuration property, which tells how many in-game seconds this state is actually executing.

publicclassMyState:MyFiniteStateMachineStateBase{publicMyState(MyFiniteStateMachinefiniteStateMachine):base(finiteStateMachine){}protectedoverridevoidExecuteHandler(infloatdeltaTime){Debug.Log($"State is executing for {ExecutionDuration} seconds");}}

About

A finite state machine for Unity

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages