AbolethSM is a custom Unreal Engine plugin for visually authoring, compiling, running, and debugging gameplay state machines. It combines a dedicated graph editor with normal Blueprint logic, reusable node classes, hierarchical state machines, multiple transition models, and live Play In Editor visualization.
Source status: Private production code. This case study documents the system and its engineering without distributing the implementation.
AbolethSM was built for Lower Management, a multiplayer cooperative looting game inspired by Lethal Company. The plugin provides a structured way to build actor and gameplay behavior without allowing large Blueprint event graphs to become the only source of truth.
The goal was to give behavior a readable high-level shape while preserving Blueprint as the place where designers implement the details.
A gameplay state machine coordinating Utility AI selection, Smart Object movement and use, fallback positioning, and shared data. The high-level behavior remains readable while reusable state classes implement the individual actions.
| Role | Systems design, C++ implementation, Unreal Editor tooling, Blueprint integration |
| Game | Lower Management |
| Genre | Multiplayer cooperative looting game |
| Engine | Unreal Engine 5.8 |
| Technology | C++, Slate, Blueprint/Kismet compiler integration, Gameplay Tags, Actor Components |
| Architecture | Separate runtime and editor modules |
| Current scale | Approximately 8,400 lines across the private runtime and editor modules |
| Status | Active production development |
The central feature is the complete workflow from visual design to live runtime inspection:
flowchart LR
A["Create a state machine asset<br/>or Aboleth Actor Blueprint"] --> B["Lay out behavior<br/>states + transitions + conduits"]
B --> C["Double-click a node<br/>to author Blueprint logic"]
C --> D["Configure transitions<br/>event + condition + timed + automatic"]
D --> E["Compile the asset<br/>into runtime data"]
E --> F["Run through an actor<br/>with an AbolethSM component"]
F --> G["Debug during PIE<br/>active state + transition history"]
G --> B
The designer creates states and connects them into an immediately readable behavior graph. An Entry node identifies the starting state, directional connections show control flow, and transition nodes describe why the machine can move.
Complex behavior can be divided into nested state machines instead of expanding one flat graph indefinitely. Any State nodes and conduits support global reactions and conditional routing.
Double-clicking a state opens its bound Blueprint graph. Each state exposes three explicit lifecycle points:
- On State Begin for setup when the state becomes active.
- On State Update for behavior that must run while active.
- On State End for cleanup when leaving the state.
Transition nodes can open a Boolean condition graph and separate transition-entered and transition-exited hooks. This keeps the behavior graph readable while allowing ordinary Blueprint nodes to implement game-specific logic.
The implementation behind the Find Smart Object state. On State Begin queries the Aboleth Utility Subsystem, compares the new selection with the current Smart Object, and exposes the result through the state's output data.
AbolethSM supports four transition models:
| Transition | Purpose |
|---|---|
| Event | React to a named gameplay event sent to the state machine |
| Condition | Evaluate authored Blueprint logic while the source state is active |
| Timed | Fire after the source state has remained active for a configured duration |
| Auto | Continue immediately when a state is entered and its transition is valid |
Transitions also support explicit priority and optional Gameplay Tag guards. These controls keep routing decisions visible in the graph rather than hiding every branch inside general-purpose Blueprint flow control.
A minimal transition condition graph. More complex transitions can use ordinary Blueprint logic and return a Boolean result through the generated condition function.
A state, transition, or conduit can use a Blueprintable node-instance class. Instance classes expose node-specific input and output properties as pins, allowing reusable behavior to be configured directly from the state machine graph.
Variable Get and Set nodes, default values, and compiled property links move data between the state machine context and node instances. This separates reusable behavior from the particular actor or asset that configures it.
The custom compiler converts editor-only graph nodes into compact generated-class data. It recursively records states, nested machines, conduits, transitions, property links, function bindings, and the root entry point.
The runtime module does not execute the visual editor graph directly. An AbolethSM component builds an owned runtime object tree from the compiled data, starts the root machine, updates active states, evaluates transitions, and broadcasts state changes.
The embedded Actor Blueprint running during simulation. The actor owns its state-machine component, State 2 is outlined as the active state, and its live 5.66-second duration is displayed above the node. The same view also exposes nested machines, actor variables, transition data pins, and Variable Get nodes.
During Play In Editor or simulation, the designer selects the actor being debugged and keeps the state machine graph open. Active states receive a live highlight, recently exited states fade over time, active transitions change color, and the current time in state is displayed.
This closes the authoring loop: the same graph used to design the behavior becomes the primary runtime diagnostic view.
The captured Lower Management example shows how AbolethSM composes with a separate Utility AI system rather than trying to replace it.
flowchart LR
A["State machine<br/>owns behavior sequence"] --> B["Find Smart Object state"]
B --> C["Utility AI subsystem<br/>scores available choices"]
C --> D["Selected Smart Object<br/>returned through state output"]
D --> E["Compiled graph data link<br/>shares the selection"]
E --> F["Move to object"]
F --> G["Use object"]
G --> B
B --> H["Random location<br/>fallback behavior"]
The state machine answers what phase of behavior is active. The Utility AI subsystem answers which available Smart Object is the best choice. A reusable state instance bridges the two by requesting a selection during On State Begin and publishing that selection as graph data.
This division keeps scoring logic independent from behavior sequencing. The state graph can change how an actor reacts to a result without rewriting the selection system, and the Utility AI implementation can evolve without turning the state graph into a scoring algorithm.
Blueprint is flexible, but complex actor behavior can become difficult to understand when lifecycle, routing, state, and implementation are mixed inside a large event graph.
The system needed to:
- Make the current behavior model understandable at a glance.
- Keep state entry, update, and exit logic clearly separated.
- Support multiple transition styles without duplicating runtime plumbing.
- Allow complex behavior to be grouped hierarchically.
- Preserve normal Blueprint authoring for game-specific logic.
- Support reusable state, transition, and conduit implementations.
- Compile editor-authored graphs into a runtime-safe representation.
- Expose runtime state changes to both Blueprint and the custom editor.
- Avoid re-entrant transition failures when gameplay events are sent during a state change.
- Provide useful compiler diagnostics before gameplay begins.
The plugin separates visual authoring, compilation, and execution:
flowchart LR
A["Custom state machine graph<br/>editor-only nodes"] --> B["AbolethSM compiler<br/>validation + graph traversal"]
B --> C["Generated class data<br/>states + transitions + bindings"]
C --> D["AbolethSM component<br/>runtime tree construction"]
D --> E["Runtime state machine<br/>active states + event routing"]
E --> F["Blueprint callbacks<br/>behavior implementation"]
E --> G["PIE debug state<br/>editor visualization"]
The runtime module contains no dependency on the editor module. Packaged builds use the generated data and runtime objects; Slate widgets, graph schemas, factories, and compiler tooling remain editor-only.
AbolethSM assets participate in the Blueprint compilation pipeline rather than acting as disconnected configuration files. State and transition subgraphs use familiar K2 Blueprint nodes, generated functions, variables, and compile results.
This gives designers a specialized high-level editor without requiring a second scripting language.
The compiler walks the custom graph recursively and emits runtime records for each state machine, state, conduit, and transition. It also maps authored Blueprint graphs to generated function names and converts data-pin connections into property links.
This establishes a deliberate boundary:
- Editor nodes describe the authored model.
- Generated data stores the compiled model.
- Runtime objects execute the model.
That separation keeps packaged-game execution independent of Slate and editor graph objects.
Every state has explicit initialization, start, update, end, and reset behavior. Nested state machines derive from the runtime state type, so a parent can treat a complete child machine as one state while the child owns its active branch.
The component creates the runtime tree with clear ownership and supplies the actor or generated state-machine instance as the execution context.
The runtime evaluates only the active states' outgoing transitions plus applicable Any State transitions. Lower numeric priority wins, allowing routing order to remain deterministic.
Transition behavior is centralized by type:
- Named events are dispatched explicitly.
- Conditions are evaluated while the source state is active.
- Timed transitions use the source state's elapsed time.
- Automatic transitions are processed on state entry.
Automatic transition chains have a depth guard, and events received during a transition are deferred until the transition completes. These protections prevent common re-entrancy and accidental infinite-loop failures.
Blueprintable node-instance classes allow behavior to be reused without copying subgraphs. The editor reflects supported properties into graph pins, and the compiler records links and defaults for runtime application.
This makes the high-level state graph both control flow and a visible configuration surface for reusable behavior.
The runtime publishes state-changed, state-tick, and transition-fired delegates. It also exposes current state, previous state, active states, time in state, history, and Gameplay Tag guard operations through Blueprint-facing APIs.
The editor uses the selected Blueprint debug object to resolve the live AbolethSM component and visualize active behavior without requiring a separate debugging window.
The custom compiler reports invalid structures before runtime, including:
- State machines with no states.
- Missing entry states.
- States with no outgoing transitions.
- Transitions with missing targets.
- Any State transitions with missing targets.
The diagnostics appear through Unreal's normal Blueprint compiler results, keeping failures inside the workflow designers already use.
flowchart TD
A(["Start"]) --> B["Initialize runtime tree"]
B --> C["Enter configured entry state"]
C --> D["Active state"]
D -->|"Update"| D
D -->|"Valid transition"| E["Exit source state"]
E --> F["Apply data links"]
F --> G["Enter target state"]
G --> D
D -->|"Stop"| H(["End"])
The component can auto-start on BeginPlay or be controlled explicitly. Gameplay can send named events, query active state, add or remove guard tags, and subscribe to lifecycle delegates.
When a transition fires, the runtime:
- Confirms its type, priority, guard, and authored condition.
- Executes transition-entered behavior.
- Ends the source state when appropriate.
- Applies compiled variable writes and property links.
- Starts the target state.
- Records history and broadcasts the state change.
- Processes valid automatic follow-up transitions.
- Executes transition-exited behavior.
The custom editor includes:
- Entry, State, nested State Machine, Transition, Conduit, and Any State nodes.
- Variable Get and Set nodes for state-machine context data.
- Custom Slate widgets for state and transition presentation.
- Directed, color-coded transition connections.
- Bound Blueprint graphs opened by double-clicking nodes.
- Asset factories for standalone state machines and actor Blueprints with an embedded machine.
- Project settings for node, transition, and PIE debug colors.
- Live active-state and recent-transition visualization.
- Custom Kismet compilation and structural validation.
| Engineering objective | Current evidence |
|---|---|
| Visual behavior authoring | Dedicated state-machine graph schema and custom Slate nodes |
| Blueprint integration | Bound state lifecycle, transition condition, and transition event graphs |
| Runtime/editor separation | Independent runtime and editor modules |
| Hierarchical composition | Nested machines compile recursively and execute as runtime states |
| Reusable behavior | Blueprintable node instances with compiled data-pin property links |
| System composition | Utility AI selection is consumed by reusable state classes and passed through the state graph |
| Deterministic routing | Explicit transition priority and scoped active-state evaluation |
| Runtime safety | Deferred transition-time events and automatic-transition depth guard |
| Debuggability | PIE active-state highlighting, time-in-state display, delegates, and state history |
| Authoring feedback | Custom compile validation through Unreal's normal compiler results |
| Game integration | Blueprint-spawnable Actor Component and optional embedded Actor Blueprint workflow |
- Complete and expose a dedicated nested-machine exit-node workflow.
- Add Unreal Automation coverage for runtime lifecycle, transition ordering, event deferral, and compiler validation.
- Profile condition-heavy machines and cache resolved property links where useful.
- Allow event-only machines to opt out of unnecessary ticking.
- Continue production testing of the newer parallel active-state workflow.
Built by JMathisPluto.
© 2026 JMathisPluto. All rights reserved. This case study does not grant permission to copy, redistribute, reverse engineer, or use the underlying proprietary implementation.



