A lightweight, performance-oriented Hierarchical State Machine (HSM) designed specifically for Unity DOTS (ECS). It allows for complex game logic management while maintaining high performance and clean system isolation by automatically managing the enabled state of ECS systems.
- Hierarchical Logic: Support for nested states and sub-states using a clean, type-safe API.
- ECS Integration: Driven by
HsmPreUpdateSystemandHsmLateUpdateSystem, fitting perfectly into the ECS update loop. - Automatic System Management: The "Killer Feature"—automatically enable or disable specific ECS Systems based on the active state using
RequiredSystems. - Editor Friendly: Includes an
HsmBootcomponent with a custom inspector for easy initialization and state selection from the Unity Scene. - Scene Transitions: Built-in
SceneTransitionStatefor handling asynchronous scene loading between states. - Zero-Boilerplate Transitions: simple
SetStateandSetSubStatemethods for fluid state changes.
- Open the Unity Package Manager (
Window > Package Manager). - Click the
+icon and selectAdd package from git URL.... - Enter the repository URL.
- For the latest version:
https://github.com/EdwardBrave/DOTS.HSM.git. - For a specific version (replace
v*.*.*with the desired version):https://github.com/EdwardBrave/DOTS.HSM.git#v*.*.*
- For the latest version:
The package is built on three main pillars:
- HsmRoot: The entry point and singleton component (
IComponentData) that holds the state machine in the ECS World. - BaseState: The base class for defining states. It handles sub-state management and
RequiredSystems. - BaseSubState<TSelf, TParent>: Used for creating states that belong to a parent state, allowing for deep hierarchies.
Define your states by inheriting from BaseSubState. Use RequiredSystems to specify which ECS systems should run only when this state is active.
using EB.DOTS.HSM;
using System;
using System.Collections.Generic;
using Unity.Entities;
public class GameplayState : BaseSubState<GameplayState, HsmRoot>
{
// These systems will be Enabled when entering GameplayState
// and Disabled when exiting it.
protected override List<Type> RequiredSystems => new()
{
typeof(PlayerMovementSystem),
typeof(EnemyAiSystem)
};
protected override void OnUpdate(SystemBase system)
{
if (UnityEngine.Input.GetKeyDown(UnityEngine.KeyCode.Escape))
{
// Transition to another state under the same parent (HsmRoot)
SetState(new PauseMenuState());
}
}
}You can initialize the HSM in two ways:
Add the HsmBoot component to a GameObject in your scene. Use the "Initial State" dropdown to select your starting state. This will automatically call HsmTools.InitHsm when the scene starts.
using EB.DOTS.HSM;
// Initialize with a starting state
HsmTools.InitHsm(new GameplayState());You can create sub-states of any state, not just HsmRoot.
public class CombatState : BaseSubState<CombatState, GameplayState>
{
protected override void OnEnter(SystemBase system)
{
UnityEngine.Debug.Log("Entered Combat!");
}
}Use the built-in SceneTransitionState to handle loading screens.
// Transition to "Level1" scene, then enter GameplayState
SetState(new SceneTransitionState("Level1", new GameplayState()));- Update Order: HSM updates during
InitializationSystemGroup(Pre-Update) andLateSimulationSystemGroup(Late-Update/Transitions). - Requirements: Requires
com.unity.entitiesversion 1.0.0 or higher. - Compatibility: Tested with Unity 2022.3+ and Unity 6.
Developed by Edward Brave. License: MIT.