Skip to content

ZellyDev-Games/monostate

Repository files navigation

Monostate

A simple, extensible state machine framework for Unity.

Monostate provides a lightweight Machine component and a base GameState class for organizing game flow, gameplay modes, UI states, combat phases, menus, cutscenes, and other state-driven systems.

Features

  • Minimal state machine implementation for Unity
  • Machine component that runs the active state
  • GameState base class with lifecycle hooks
  • Per-frame Update(float deltaTime) forwarding
  • Physics-step FixedUpdate(float fixedDeltaTime) forwarding
  • Extensible design for project-specific machines and state types
  • No external dependencies

Installation

Install through Unity Package Manager using the Git URL:

https://github.com/ZellyDev-Games/monostate.git

Or add it directly to your Unity project's Packages/manifest.json:

{
  "dependencies": {
    "com.github.zellydev-games.monostate": "https://github.com/ZellyDev-Games/monostate.git"
  }
}

Package Info

{
  "name": "com.github.zellydev-games.monostate",
  "version": "1.0.0",
  "displayName": "Monostate",
  "unity": "6000.3"
}

Core Concepts

Monostate has two primary types:

Machine

Machine is a Unity MonoBehaviour that owns the current state.

It exposes:

public GameState CurrentState { get; private set; }
public void ChangeState(GameState newState)

Each frame, the machine forwards Unity updates to the current state:

CurrentState?.Update(Time.deltaTime);
CurrentState?.FixedUpdate(Time.fixedDeltaTime);

GameState

GameState is the base class for individual states.

Override any of these lifecycle methods:

public virtual void OnEnter(Machine machine)
public virtual void OnExit()
public virtual void Update(float deltaTime)
public virtual void FixedUpdate(float fixedDeltaTime)

OnEnter receives the owning Machine and stores it for later use.

Basic Usage

Create a state by deriving from GameState:

using UnityEngine;
using ZellyDevGames.Monostate;

public class TitleState : GameState
{
    public override void OnEnter(Machine machine)
    {
        base.OnEnter(machine);

        Debug.Log("Entered title state.");
    }

    public override void Update(float deltaTime)
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Machine.ChangeState(new GameplayState());
        }
    }

    public override void OnExit()
    {
        Debug.Log("Leaving title state.");
    }
}

Create another state:

using UnityEngine;
using ZellyDevGames.Monostate;

public class GameplayState : GameState
{
    public override void OnEnter(Machine machine)
    {
        base.OnEnter(machine);

        Debug.Log("Gameplay started.");
    }

    public override void Update(float deltaTime)
    {
        // Gameplay update logic
    }

    public override void FixedUpdate(float fixedDeltaTime)
    {
        // Physics-timed gameplay logic
    }
}

Attach a Machine component to a GameObject, then change to your starting state:

using UnityEngine;
using ZellyDevGames.Monostate;

public class GameBootstrap : MonoBehaviour
{
    [SerializeField] private Machine machine;

    private void Start()
    {
        machine.ChangeState(new TitleState());
    }
}

State Transitions

States are responsible for their own transition logic.

The base Machine does not validate transition graphs. This keeps the framework simple and makes it easy to define your own rules inside individual states or in a derived machine class.

public override void Update(float deltaTime)
{
    if (ShouldStartBattle())
    {
        Machine.ChangeState(new BattleState());
    }
}

When ChangeState is called, the machine:

  1. calls OnExit() on the current state, if one exists
  2. assigns the new state to CurrentState
  3. calls OnEnter(this) on the new state

Extending Machine

The base Machine intentionally contains no project-specific data stores.

For larger projects, create your own machine type with references to the systems your states need:

using UnityEngine;
using ZellyDevGames.Monostate;

public class GameMachine : Machine
{
    public PlayerController Player;
    public Camera MainCamera;
    public Transform SpawnPoint;
}

Then create a specialized state base class so states do not need to cast repeatedly:

using ZellyDevGames.Monostate;

public abstract class GameStateBase : GameState
{
    protected GameMachine GameMachine { get; private set; }

    public override void OnEnter(Machine machine)
    {
        base.OnEnter(machine);

        GameMachine = (GameMachine)machine;
    }
}

Now project states can access the typed machine directly:

public class ExploreState : GameStateBase
{
    public override void OnEnter(Machine machine)
    {
        base.OnEnter(machine);

        GameMachine.Player.enabled = true;
    }
}

Important Notes

  • Always call base.OnEnter(machine) when overriding OnEnter.
  • The base OnEnter stores the owning machine reference.
  • Calling base.OnExit(), base.Update(...), or base.FixedUpdate(...) is optional because the base implementations are empty.
  • The default Machine performs no transition validation.
  • State graph rules should live in your states, a custom machine, or another project-specific layer.
  • GameState instances are plain C# objects, not MonoBehaviour components.
  • Machine is the Unity component that connects the state system to Unity's Update and FixedUpdate loops.

Recommended Uses

Monostate works well for:

  • Game flow
  • Main menu flow
  • Combat phases
  • Turn-based battle states
  • Player control modes
  • UI screens
  • Cutscene sequencing
  • Tool/editor workflows
  • Puzzle or minigame modes

Example State Flow

BootState
  -> TitleState
  -> MainMenuState
  -> GameplayState
      -> PauseState
      -> BattleState
      -> GameOverState

API Reference

Machine.CurrentState

public GameState CurrentState { get; private set; }

The currently active state.

Machine.ChangeState

public void ChangeState(GameState newState)

Exits the current state, assigns the new state, and enters it.

GameState.OnEnter

public virtual void OnEnter(Machine machine)

Called when the machine activates this state.

GameState.OnExit

public virtual void OnExit()

Called before the machine switches away from this state.

GameState.Update

public virtual void Update(float deltaTime)

Called from the owning machine's Unity Update.

GameState.FixedUpdate

public virtual void FixedUpdate(float fixedDeltaTime)

Called from the owning machine's Unity FixedUpdate.

License

MIT

About

A simple, extensible state machine framework and implementation for Unity.

Resources

License

MIT, Unknown licenses found

Licenses found

MIT
LICENSE
Unknown
LICENSE.meta

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages