Skip to content

Repository files navigation

Fynite

Write your states in C#. Fynite runs them from the Unity PlayerLoop.

A code-first state machine for Unity 6, composed with generics and driven without a single machine.Update() call.

Release workflow Release Unity License


Why Fynite?

A state machine usually costs you two things: a graph asset only the editor can review, and a machine.Update() call every controller has to remember. Fynite drops both.

States, conditions and routing are ordinary classes named through generics, so a rename stays a rename and a pull request stays readable. Transitions live in their own modules, which lets a state be reordered or reused without touching it. Build() hands the machine to the PlayerLoop and the owner's lifetime ends it.

Cost stays where you can see it: setup allocates, the per-frame path does not, and nothing anywhere uses reflection or LINQ.

Features

  • Compiler-checked composition — states, predicates and transitions are classes named through generics.
  • PlayerLoop executionBuild() registers the machine; destroying the owner stops it, disabling it pauses.
  • Events beside predicatesFyniteEvent carries occurrences, predicates answer standing questions.
  • Activities — a state runs a chain of timed steps, with no coroutine involved.
  • Optional hierarchy — a parent state shares its transitions with every child.
  • Editor debuggerTools > Fynite > Debugger lists running machines and their active path.
  • No per-frame allocation — the update path, Publish() and activity steps allocate nothing.

Installation

Requires Unity 6000.5 or newer, and depends on no other package.

The latest published release is v0.15.0.

In the Unity Package Manager, choose Add package from git URL and paste:

https://github.com/Natteens/fynite.git#v0.15.0

Or declare the dependency in Packages/manifest.json:

{
  "dependencies": {
    "com.natteens.fynite": "https://github.com/Natteens/fynite.git#v0.15.0"
  }
}

Pin a tag. A URL without #<tag> follows main, which can carry the version number of the last release and different code. Every tag is listed on the releases page.

Quick Start

using Fynite;
using UnityEngine;

public sealed class PlayerController : MonoBehaviour
{
    [SerializeField] private PlayerInput input;
    [SerializeField] private PlayerMovement movement;

    private void Awake()
    {
        Machine
            .Attach(this, new PlayerContext(input, movement))
            .Start<IdleState>()
            .Use<LocomotionTransitions>()
            .Build();
    }
}

public sealed class IdleState : FyniteState<PlayerContext>
{
    protected override void Enter() => Context.Movement.Stop();
}

public sealed class LocomotionTransitions : IFyniteTransitions<PlayerContext>
{
    public void Configure(FyniteTransitions<PlayerContext> transitions)
    {
        transitions
            .From<IdleState, WalkState>()
            .When(HasMovement);

        transitions
            .From<WalkState, IdleState>()
            .When(HasNoMovement);
    }

    private static bool HasMovement(PlayerContext context)
        => context.Input.HasMovement;

    private static bool HasNoMovement(PlayerContext context)
        => !HasMovement(context);
}

Every state named by Start, From or To is created once, while Build() runs. The controller holds no reference and implements no Update, FixedUpdate or OnDestroy.

The Code First sample builds the same idea with a hierarchy, events and an activity. Import it from the Package Manager, under the Samples tab.

Documentation

License

MIT. See LICENSE.md.

About

A code-first hierarchical state machine for Unity with deterministic runtime execution and graph-based authoring.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages