UniState
UniState is a modern, high-performance, scalable state machine package for Unity.
Install / Use
/learn @bazyleu/UniStateREADME
UniState
UniState is a modern, high-performance, scalable state machine package for Unity. It can serve as a core architectural pattern or be used to address specific tasks.
- Performance: optimized for minimal runtime allocations, see performance section for details.
- Modularity: designed to define states, substates, and state machines in an isolated way. States can be easily replaced or removed without hidden effects even in big projects.
- Scalability: memory allocations happen only on demand, performance does not degrade with the number of states and state machines.
- Asynchronous: modern asynchronous API with async-await and UniTask
- Reliability: allows you to define global error handling at the state machine level, and guarantees that all resources will be disposed.
- Simplicity: if you use state base you have to implement only one method for fast start.
- Flexibility: everything in framework core is an abstraction. Can be replaced with your own implementation, see state creating and creating a state machine sections for details.
- Testability: UniState is designed to be testable. All abstractions use interfaces that can be easily mocked with NSubstitute or any other framework. States can be run separately for testing purposes.
- DI friendly: has integration with most popular DI containers
- Continuous Testing: fully covered by tests. All tests run automatically to verify each change.
Table of Contents
<!-- TOC start (generated with https://github.com/derlin/bitdowntoc) -->- Getting Started
- Installation
- Performance
- Framework Philosophy
- API Details and Usage
- Tutorials
- Integrations
- License
Getting Started
Step 1:
Install UniState by adding the following URL to Unity Package Manager:
https://github.com/bazyleu/UniState.git?path=Assets/UniState.
Details on installation are available here.
Step 2: Create a state by defining a class that inherits from StateBase or StateBase<T>. Example transition logic:
public class MainMenuState : StateBase
{
public override async UniTask<StateTransitionInfo> Execute(CancellationToken token)
{
// Add your state logic here
return Transition.GoTo<GameplayState>();
}
}
public class GameplayState : StateBase
{
public override async UniTask<StateTransitionInfo> Execute(CancellationToken token)
{
// Add your state logic here
return Transition.GoBack();
}
}
Detailed information about creating states is available here.
Step 3: Configure Dependency Injection (DI) by registering the state machine and states in the DI container.
builder.RegisterStateMachine<IStateMachine, StateMachine>();
builder.RegisterState<MainMenuState>();
builder.RegisterState<GameplayState>();
Additional information on DI configuration is available here.
Step 4: Create and run the state machine by specifying the initial state.
public class Game
{
// Note that you must resolve the interface but not the implementation
private readonly IStateMachine _stateMachine;
public Game(IStateMachine stateMachine)
{
_stateMachine = stateMachine;
}
public void Start()
{
_stateMachine.Execute<MainMenuState>(CancellationToken.None).Forget();
}
}
More details on running the state machine can be found here.
That's it! Your first UniState project is set up. You can find a more detailed walkthrough in the tutorials section.
Installation
Requirements
- Requires Unity version 2022.3 or higher.
- Requires UniTask package installed. Guide regarding UniTask installation can be found on Cysharp/UniTask README.
Option 1: Add package from git URL
You can add https://github.com/bazyleu/UniState.git?path=Assets/UniState to Package Manager.
It is a good practice to specify target version, UniState uses the *.*.* release tag so you can specify a version
like #1.9.0. For example https://github.com/bazyleu/UniState.git?path=Assets/UniState#1.9.0.
You can find latest version number here.
Option 2: Add via manifest.json
You can add "com.bazyleu.unistate": "https://github.com/bazyleu/UniState.git?path=Assets/UniState" (or with version
tag https://github.com/bazyleu/UniState.git?path=Assets/UniState#1.9.0) to Packages/manifest.json.
Performance
UniState is the fastest and most efficient asynchronous state machine available for Unity. When compared to state machine implementations based on MonoBehaviour, UniState delivers a performance boost of over 5000x in execution speed and up to a 10x reduction in allocations.
For typical scenarios involving small to medium state chains - the most common use case - UniState can reduce memory allocations by a factor ranging between 2x and 10x. In cases where state chains exceed 200 states, the benefits in memory allocation become less pronounced, but execution speed remains consistent with a 5000x+ boost.
Measurements for Windows PC (with IL2CPP scripting backend):
Benchmark Mono 10 states: 516.4 ms, 120.83 KB
Benchmark Mono 50 states: 2520.9 ms, 150.44 KB
Benchmark Mono 200 states: 10033.6 ms, 283.83 KB
Benchmark UniState 10 states: 0.1 ms, 13.11 KB
Benchmark UniState 50 states: 0.2 ms, 68.81 KB
Benchmark UniState 200 states: 0.7 ms, 273.20 KB
Benchmark UniState with history 10 states: 0.1 ms, 14.34 KB
Benchmark UniState with history 50 states: 0.2 ms, 69.58 KB
Benchmark UniState with history 200 states: 0.7 ms, 276.95 KB
Framework Philosophy
Dependency Injection
All dependencies for states, commands, and other entities should be passed through the constructor. UniState supports automatic integration with the most popular DI frameworks for Unity. Refer to the integration documentation for more details. Dependencies must be registered in your DI framework, and they will automatically be resolved when creating state
