Plugin Documentation

FlowKit
Latent flow helpers for C++ and Blueprints

Delays, tickers, timelines, conditional waits, time locks, background tasks and async loading as one-line latent actions with handles - plus C++20 coroutine awaiters on Unreal Engine 5.8.

v1.0
UE 4.27 & 5.8
Win64 only
Category Programming
Alpha XP

Overview

FlowKit replaces timers, tick functions and hand-written state machines with one-line latent actions. Start a delay, ticker, timeline or conditional wait from C++ with a lambda, or from Blueprints with an async node. Actions run inside a game-instance subsystem (UFKSubsystem), are bound to an owner object, and are removed automatically when that owner is destroyed.

  • Timing: Delay, Delay Ticks, Ticker (for a duration, forever or until stopped).
  • Timelines: float, Vector and LinearColor value timelines with linear, cubic and ease blending, plus custom timelines driven by curve assets.
  • Conditions: Wait And Execute (run once a predicate is true) and While True Execute (tick while a predicate is true), both with optional time-outs.
  • Gates: Time Lock, Do Once, Do N Times and Do No More Than X Time, keyed by instance ids.
  • Async: run a task on a background thread and continue on the game thread; load soft object paths asynchronously.
  • Control: every action returns a handle to pause, resume, reset, stop or re-time it; stop all actions, by class or by label; pause the whole subsystem.
  • Coroutines (UE 5.8, C++20): write a whole sequence top to bottom with co_await.

Requirements

RequirementDetails
Unreal Engine4.27 and 5.8 (verified clean on both). The coroutine API requires 5.8.
ModulesFlowKit (Runtime, loading phase Default)
DependenciesNone
LanguageBlueprints and C++ (coroutines: C++ only)
PlatformsWin64 only - the plugin descriptor allows Win64 alone, and Win64 is the platform built and verified by Alpha XP.

Installation

  1. Copy the FlowKit folder into your project's Plugins/ folder (create it if needed), or install the plugin to the engine from Fab.
  2. Open the project. For a C++ project, let the editor build the module or build it from your IDE.
  3. Enable FlowKit in Edit > Plugins (category Programming) and restart the editor.
  4. C++ only: add "FlowKit" to PublicDependencyModuleNames in your module's Build.cs and include FlowKit.h.
Verifying the installRight-click in an actor's Event Graph and search for FlowKit: the FlowKit category lists nodes such as FlowKit - Delay and FlowKit - Ticker. In game, stat FlowKit shows the number of running actions.

Quick start

Blueprint

  1. In an actor's Event Graph, add FlowKit - Delay after Event BeginPlay and set Delay Time to 2.
  2. Connect your logic to the On Complete output pin; its Stopped value is true when the delay was stopped early. The top exec pin continues immediately.
  3. Promote the Handle output to a variable. Later, call FlowKit - Stop Action with that handle to cancel the delay, or FlowKit - Pause Action / FlowKit - Resume Action to pause it.
  4. Expand Settings (advanced pins) to set a tick interval, a first delay, ignore game pause or time dilation, start paused, or a Label.

C++

#include "FlowKit.h"

void AMyActor::BeginPlay()
{
    Super::BeginPlay();

    // Run code after 2 seconds; dropped automatically if this actor is destroyed.
    DelayHandle = FFlowKit::Delay(this, 2.f, [this]()
    {
        UE_LOG(LogTemp, Log, TEXT("Two seconds later"));
    });

    // Blend a value from 0 to 1 over 3 seconds with ease-in-out.
    FFlowKit::AddTimeline(this, 0.f, 1.f, 3.f, [this](float Value, float Time)
    {
        FadeAlpha = Value;
    }, [this](float Value, float Time, bool bStopped)
    {
        UE_LOG(LogTemp, Log, TEXT("Fade finished"));
    }, EFKBlendFunc::FKBlend_EaseInOut, 2.f);

    // Tick every 0.5 s for 10 s, ignoring game pause.
    FFlowKit::AddTicker(this, 10.f, [this](float DeltaTime)
    {
        UpdateRadar();
    }, [this](bool bStopped)
    {
        UE_LOG(LogTemp, Log, TEXT("Ticker finished"));
    }, FFKActionSettings().WithTickInterval(0.5f).WithIgnorePause());

    // Run once a condition is true, with a 5 second time-out.
    FFlowKit::WaitAndExecute(this, [this]() { return bIsReady; }, [this](bool bTimedOut)
    {
        StartMatch();
    }, 5.f);
}

void AMyActor::CancelDelay()
{
    FFlowKit::StopAction(this, DelayHandle);   // FFKHandle DelayHandle member; the handle is invalidated
}

Concepts

Owner and world

The first argument of every launch function is the owner. It also provides the world, whose game instance hosts UFKSubsystem. When the owner is destroyed the action is removed without calling its callback. Actions only tick in game and Play-In-Editor worlds, and must be started from the game thread.

Handles

Launch functions return an FFKHandle (Blueprint: FFKHandleBP). An invalid handle means the action could not start (for example a negative time or an empty callback; the reason is logged to LogFlowKit). A handle stays valid after its action ends; use FlowKit - Is Action Running / IsActionRunning to check it.

Stopping and completing

Stop functions take bComplete: false (default) removes the action silently, true runs its completion callback with bStopped = true.

Instance ids

Gates (Time Lock, Do Once, Do N Times, Do No More Than X Time) take an FFKInstanceId (Blueprint: FFKInstanceIdBP). Only one action runs per instance id; launching it again re-triggers the running one. Create ids with FFKInstanceId::NewId() or FlowKit - Get New Instance Id.

Action settings

Field (FFKActionSettings)DefaultDescription
TickInterval0Seconds between ticks; 0 ticks every frame. Builder: WithTickInterval(float), macro FLOWKIT_TICKINTERVAL(x).
FirstDelay0Delay before the first tick. WithFirstDelay(float), FLOWKIT_DELAYFIRST(x).
bIgnorePausefalseKeeps ticking while the game is paused. WithIgnorePause(), FLOWKIT_IGNOREPAUSE.
bIgnoreGlobalTimeDilationfalseUses undilated delta time. WithIgnoreGlobalTimeDilation(), FLOWKIT_IGNORETIMEDILATION; both flags: FLOWKIT_IGNOREPAUSEDILATION.
bStartPausedfalseStarts the action paused; resume it with its handle. WithStartPaused(), FLOWKIT_STARTPAUSED.
LabelemptyFree text used by FlowKit - Stop All Actions With Label and the label queries. WithLabel(FString), FLOWKIT_LABEL(x).

Blend functions

EFKBlendFunc: FKBlend_Linear, FKBlend_Cubic, FKBlend_EaseIn, FKBlend_EaseOut, FKBlend_EaseInOut. BlendExp (default 1) is the exponent of the ease functions. EFKAsyncPrio: Normal, HiPriority (background thread priority).

Blueprint async nodes

Category FlowKit. Each node returns immediately through its top exec pin, outputs a Handle, and fires the listed output pins later. Settings is an advanced pin.

NodeTypeDescription
FlowKit - DelayAsyncInputs: Delay Time. Output: On Complete (Stopped).
FlowKit - Delay TicksAsyncInputs: Delay Ticks (frames). Output: On Complete (Stopped).
FlowKit - TickerAsyncInputs: Ticking Time (-1 ticks until stopped). Outputs: On Tick (Delta Time), On Complete (Stopped).
FlowKit - Wait And ExecuteAsyncInputs: In Time Out (0 = none). On Wait fires every tick with the action object: call FlowKit - Predicate (WaitAndExecute) on it with true to finish. Output On Execute (Timed Out, Stopped).
FlowKit - Predicate (WaitAndExecute)CallableCalled on the Action output of Wait And Execute; Has Finished = true runs On Execute.
FlowKit - While True ExecuteAsyncInputs: Time Out. On While asks for the condition (call the predicate below), On Execute fires every tick while it is true (Delta Time), On Complete fires at the end (Timed Out, Stopped).
FlowKit - Predicate (WhileTrueExecute)CallableCalled on the Action output of While True Execute; Is True = false ends the loop.
FlowKit - TimelineAsyncInputs: Start Value, Stop Value, Time, Blend Func, Blend Exp. Outputs: On Tick and On Finished (Value, Time, Stopped).
FlowKit - Timeline VectorAsyncSame as Timeline with Vector values.
FlowKit - Timeline LinearColorAsyncSame as Timeline with LinearColor values.
FlowKit - Custom TimelineAsyncInput: Curve Float asset; plays the curve from the start to its last key. Outputs: On Tick, On Finished (Value, Time, Stopped).
FlowKit - Custom Timeline VectorAsyncSame with a Curve Vector asset.
FlowKit - Custom Timeline LinearColorAsyncSame with a Curve Linear Color asset.
FlowKit - Do No More Than X TimeAsyncInputs: Time, Instance Id, Max Execs Enqueued (default 1). On Execute fires at once, then at most once per Time; extra calls are queued up to the maximum.
FlowKit - Run Async ThenAsyncInputs: In Time Out, Priority. Async Task fires on a background thread; On Execute fires on the game thread when it is done (Timed Out, Stopped).
FlowKit - Load Objects AsyncAsyncInput: Objects To Load (soft object paths). Output: On Complete (Stopped) once all are loaded.
Run Async Then in BlueprintsThe Async Task pin executes on a background thread. Only connect thread-safe work there (no spawning, no UObject or widget changes); do game-thread work from On Execute.

Blueprint utility nodes

Static functions of UFKBPLibrary, category FlowKit.

NodeTypeDescription
FlowKit - Time LockCallableExec outputs Exec / Locked: runs Exec at most once per Lock Time for an Instance Id; otherwise Locked.
FlowKit - Set Pause SubsystemCallablePauses or resumes every FlowKit action of the world's game instance.
FlowKit - Get Pause SubsystemPureReturns whether the subsystem is paused.
FlowKit - Is Action RunningPureTrue while the action of the handle is running or pending.
FlowKit - Is Action PausedPureOutputs Is Running and Is Paused.
FlowKit - Pause ActionCallablePauses one action.
FlowKit - Resume ActionCallableResumes one action.
FlowKit - Reset ActionCallableRestarts an action that supports resetting (optionally calling its update); returns whether it was reset.
FlowKit - Get Action TimePureCurrent time value of a delay, ticker, timeline or lock; -1 if unsupported.
FlowKit - Set Action TimeCallableSets that time value (optionally calling the update); returns false if unsupported.
FlowKit - Stop ActionCallableStops one action and invalidates the handle; Complete runs its callback.
FlowKit - Stop Instanced ActionsCallableStops the action of an instance id.
FlowKit - Stop All ActionsCallableStops every action, optionally only those of In Owner.
FlowKit - Stop All Actions Of ClassCallableStops every action of a class (for example FKDelay), optionally per owner.
FlowKit - Stop All Actions With LabelCallableStops every action with a label, optionally per owner.
FlowKit - Get Actions Handles By ClassPureHandles of running or pending actions of a class.
FlowKit - Get Actions Handles By LabelPureHandles of running or pending actions with a label.
FlowKit - Get Action Label By HandlePureLabel of the action of a handle.
FlowKit - Is Handle ValidPureTrue if the handle refers to an action that was started.
FlowKit - Get New Instance IdPureCreates a new instance id.
FlowKit - Validate Instance IdPureReturns the id, creating a new one when it is invalid.
FlowKit - Is Instance Id ValidPureTrue if the instance id is valid.
FlowKit - Convert Soft Objects To Soft PathsCallableConverts soft object references to soft object paths for FlowKit - Load Objects Async.
FlowKit - Convert Soft Classes To Soft PathsCallableConverts soft class references to soft object paths.
ToString (FFKHandleBP)PureAuto-cast of a handle to a string.
ToString (FFKInstanceIdBP)PureAuto-cast of an instance id to a string.

Deprecated nodes

Kept for compatibility and marked deprecated in the editor; use FlowKit - Stop All Actions Of Class instead.

NodeTypeDescription
FlowKit - Remove All Time LocksCallableStops all time locks.
FlowKit - Remove All DelaysCallableStops all delays.
FlowKit - Remove All Wait And ExecutesCallableStops all Wait And Execute actions.
FlowKit - Remove All While True ExecutesCallableStops all While True Execute actions.
FlowKit - Remove All Run Async ThensCallableStops all Run Async Then actions.
FlowKit - Remove All TickersCallableStops all tickers.
FlowKit - Remove All TimelinesCallableStops all float timelines.
FlowKit - Remove All Timelines VectorCallableStops all Vector timelines.
FlowKit - Remove All Timelines LinearColorCallableStops all LinearColor timelines.
FlowKit - Remove All Custom TimelinesCallableStops all float custom timelines.
FlowKit - Remove All Custom Timelines VectorCallableStops all Vector custom timelines.
FlowKit - Remove All Custom Timelines LinearColorCallableStops all LinearColor custom timelines.
FlowKit - Remove All Do No More Than X TimesCallableStops all Do No More Than X Time actions.

C++ API

All functions are static members of FFlowKit (header FlowKit.h). Launch functions take the owner first and return an FFKHandle; callbacks are lambdas, and most have overloads with and without the bStopped / bTimedOut parameters. The last parameter is an optional FFKActionSettings.

FunctionKindDescription
DelayLaunch(Owner, DelayTime, Callback); callback void() or void(bool bStopped).
DelayTicksLaunch(Owner, int32 Ticks, Callback).
AddTickerLaunch(Owner, [TickingTime], TickFunc, [Callback]); tick void(float) or void(float, FFKHandle); without a time (or -1) it ticks until stopped.
WaitAndExecuteLaunch(Owner, Predicate, Callback, TimeOut = 0); predicate bool() or bool(float DeltaTime).
WhileTrueExecuteLaunch(Owner, Predicate, TickFunc, CompleteFunc, TimeOut = 0).
AddTimeline / AddTimelineVector / AddTimelineLinearColorLaunch(Owner, Start, Stop, Time, TickFunc, [Callback], BlendFunc, BlendExp).
AddCustomTimeline / AddCustomTimelineVector / AddCustomTimelineLinearColorLaunch(Owner, Curve, TickFunc, [Callback]) with UCurveFloat, UCurveVector or UCurveLinearColor.
TimeLockLaunch(Owner, LockTime, ExecFunc, InstanceId); runs at once, then ignores calls until the lock time passes.
DoOnceLaunch(Owner, ExecFunc, InstanceId); runs once per instance id; further launches are ignored until the action is reset or stopped.
DoNTimesLaunch(Owner, Times, ExecFunc(int32 Counter), InstanceId).
DoNoMoreThanXTimeLaunch(Owner, ExecFunc, Time, MaxExecsEnqueue, InstanceId).
RunAsyncThenLaunch(Owner, AsyncTaskFunc, Callback, TimeOut = 0, Priority); the task runs on a background thread, the callback on the game thread.
LoadObjectsAsyncLaunch(Owner, TArray<FSoftObjectPath>, Callback). ConvertSoftPtrToSoftPath converts soft pointer arrays.
IsActionRunning / IsActionPausedQueryState of an action.
PauseAction / ResumeAction / ResetActionControlControl one action.
GetActionTime / SetActionTimeControlRead or set the time value of an action.
StopAction / StopInstancedActionControlStop one action (bComplete runs its callback).
StopAllActions / StopAllActionsOfClass / StopAllActionsWithLabelControlStop groups of actions; StopAllActionsOfClass<UFKDelay>(this) has a template form.
SetPause / GetPauseControlPause the whole subsystem.
GetActionsHandlesByClass / GetActionsHandlesByLabelQueryFind handles.
GetAllActions / GetActionsCount / GetActionFromHandle / GetActionLabelFromHandle / GetActionFromInstancedIdDebugInspect running actions.

The RemoveAll... functions of FFlowKit are deprecated in favour of StopAllActionsOfClass. Action classes: UFKDelay, UFKDelayTicks, UFKTicker, UFKWaitAndExecute, UFKWhileTrueExecute, UFKTimeline, UFKTimelineVector, UFKTimelineLinearColor, UFKCustomTimeline, UFKCustomTimelineVector, UFKCustomTimelineLinearColor, UFKTimeLock, UFKDoOnce, UFKDoNTimes, UFKDoNoMoreThanXTime, UFKRunAsyncThen, UFKLoadObjectsAsync.

Coroutines (UE 5.8)

On Unreal Engine 5.8 (C++20) FLOWKIT_WITH_COROUTINES is 1 and a member function returning FFKCoroutine can co_await FlowKit awaiters. On UE 4.27 the macro is 0 and FFKCoroutine is void, so the declaration still compiles; guard the body as shown when the same source must build on both engines.

// MyComponent.h
FFKCoroutine IntroSequence();

// MyComponent.cpp
#include "FlowKit.h"

FFKCoroutine UMyComponent::IntroSequence()
{
#if FLOWKIT_WITH_COROUTINES
    const bool bStopped = co_await FFlowKit::WaitSeconds(this, 2.f);
    if (bStopped)
    {
        co_return;
    }
    co_await FFlowKit::WaitTicks(this, 1);
    const FFKCoroutineAwaiter_ResultWithTimeout Ready = co_await FFlowKit::WaitUntil(this, [this]() { return bIsReady; }, 5.f);
    if (Ready.bTimedOut == false)
    {
        co_await FFlowKit::RunAsyncAndWait(this, []() { /* background work */ });
    }
#endif
}
AwaiterKindDescription
WaitSecondsco_awaitWaits a time; returns bool bStopped.
WaitTicksco_awaitWaits a number of ticks; returns bStopped.
WaitUntilco_awaitWaits for a predicate (bool() or bool(float)) with optional time-out; returns FFKCoroutineAwaiter_ResultWithTimeout (bStopped, bTimedOut).
WaitForFlagco_awaitWaits until a bool* becomes true, with optional time-out.
LoopAndWaitco_awaitTicks a function while a predicate is true, with optional time-out.
RunAsyncAndWaitco_awaitRuns a task on a background thread and resumes on the game thread.
WaitLoadObjectsco_awaitLoads soft object paths or primary asset ids asynchronously; returns bStopped.

If the owner is destroyed while a coroutine is suspended, the coroutine is destroyed without resuming.

Profiling and logs

  • stat FlowKit shows the number of actions, instanced actions and action objects; stat FlowKitDetails shows the tick cost per action type.
  • Unreal Insights shows FlowKit - ... Tick scopes while FLOWKIT_INSIGHT_PROFILING is 1 (default).
  • Messages use the LogFlowKit category. FLOWKIT_LOGS and FLOWKIT_LOGS_VERBOSE are set in Source/FlowKit/FlowKit.Build.cs.

Troubleshooting

SymptomCause and fix
Action never runs and the handle is invalidSetup failed: check LogFlowKit for the reason (for example a negative or zero time, an empty callback or a missing curve).
Nothing happens in an editor utility or editor worldThe subsystem only ticks in game and Play-In-Editor worlds. Start actions from gameplay objects.
Error: Can't obtain GameInstance from WorldContextObjectThe owner has no world with a game instance (for example a default object or an asset). Pass an actor, component or other object that lives in the game world.
Callback did not fire after the actor was destroyedBy design: actions are removed silently when their owner is destroyed. Use an owner that lives long enough, or stop the action with bComplete = true before destroying it.
Action stops while the game is pausedPaused worlds pause FlowKit actions unless bIgnorePause is set in the action settings.
AddTicker / AddTimeline call is ambiguousEach of these functions has callback overloads with and without bStopped, so a missing or nullptr callback cannot pick one. Always pass a callback lambda (it may be empty), for example [](bool bStopped) {}.
Crash or assert when starting an action from another threadActions must be started from the game thread. Use RunAsyncThen to move work to a background thread and back.
co_await does not compile on UE 4.27Coroutines require UE 5.8 (C++20). Guard coroutine bodies with #if FLOWKIT_WITH_COROUTINES.

Credits

© 2026 Alpha XP — alphaxp.net · Support: support@alphaxp.net. Built and verified for Unreal Engine 4.27 and 5.8.