https://github.com/madeyellow/finitestatemachine
A finite state machine for Unity
https://github.com/madeyellow/finitestatemachine
csharp dotnet finite-state-machine fsm unity
Last synced: 2 months ago
JSON representation
A finite state machine for Unity
- Host: GitHub
- URL: https://github.com/madeyellow/finitestatemachine
- Owner: madeyellow
- License: mit
- Created: 2024-02-28T12:08:40.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-10-27T05:05:29.000Z (over 1 year ago)
- Last Synced: 2024-10-28T06:51:36.499Z (over 1 year ago)
- Topics: csharp, dotnet, finite-state-machine, fsm, unity
- Language: C#
- Homepage:
- Size: 40 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# 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
```

## 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:
```csharp
using MadeYellow.FSM;
using UnityEngine;
///
/// Base for any state in our FSM, refrencing FSM
///
public abstract class MyFiniteStateMachineStateBase : StateBase
{
protected readonly MyFiniteStateMachine FiniteStateMachine;
public MyFiniteStateMachineStateBase(MyFiniteStateMachine finiteStateMachine)
{
FiniteStateMachine = finiteStateMachine;
}
}
///
/// Example of some state
///
public class MyState : MyFiniteStateMachineStateBase
{
private float _time;
public MyState(MyFiniteStateMachine finiteStateMachine) : base(finiteStateMachine)
{
}
protected override void ExecuteHandler(in float deltaTime)
{
// This is logic of your state. You may implement anything here.
_time += deltaTime;
Debug.Log($"{_time} has passed");
}
}
///
/// Your FSM
///
public class MyFiniteStateMachine : FiniteStateMachineBase
{
public readonly MyState SomeState;
public readonly MyState SomeOtherState;
public MyFiniteStateMachine()
{
SomeState = new MyState(this);
SomeOtherState = new MyState(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:
```csharp
public class BasicCharacter : MonoBehaviour
{
private MyFiniteStateMachine _fsm;
private void Awake()
{
_fsm = new MyFiniteStateMachine();
}
private void FixedUpdate()
{
_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:
```csharp
public override void CheckTransitions()
{
// Some condition to transition from this state. CheckTransitions() of CurrentState executes before ExecuteHandler() each time you call Execute() in your FSM
if (_time > 1)
{
// A way to change state of FSM. FSM will use ExecuteHandler of SomeOtherState instead of this state
FiniteStateMachine.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:
```csharp
public class BasicCharacter : MonoBehaviour
{
private MyFiniteStateMachine _fsm;
private void SomeMethod()
{
var currentState = _fsm.CurrentState;
var previousState = _fsm.PreviousState;
}
}
```
You may even use it inside your state to define various logic based on the previous state:
```csharp
public class MyState : MyFiniteStateMachineStateBase
{
private float _time;
public MyState(MyFiniteStateMachine finiteStateMachine) : base(finiteStateMachine)
{
}
protected override void ExecuteHandler(in float deltaTime)
{
// Execute only if previous state was SomeState
if (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.
```csharp
public class BasicCharacter : MonoBehaviour
{
private MyFiniteStateMachine _fsm;
private void Awake()
{
_fsm = new MyFiniteStateMachine();
_fsm.OnCurrentStateChanged.AddListener(OnStateChanged); // Subscribes to change of state in _fsm
}
private void OnStateChanged()
{
// 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:
```csharp
protected override void StateEnteringHook()
{
Debug.Log($"MyState entereted"); // This will be called when FSM enter your state
}
protected override void StateExitingHook()
{
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.
```csharp
public class BasicCharacterAnimator : MonoBehaviour
{
private MyFiniteStateMachine _fsm;
private void Awake()
{
_fsm.SomeState.OnEnteredState.AddListener(OnSomeStateEntered);
}
private void OnSomeStateEntered() {}
}
```
### 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.
```csharp
public class MyState : MyFiniteStateMachineStateBase
{
public MyState(MyFiniteStateMachine finiteStateMachine) : base(finiteStateMachine)
{
}
protected override void ExecuteHandler(in float deltaTime)
{
Debug.Log($"State is executing for {ExecutionDuration} seconds");
}
}
```