Skip to content

Creating Your Own Task ​

A Task has a short life: Setup once per flow execution, Enter when it starts, Tick every frame until it finishes, then Exit. A Task finishes when it calls Finish Task (success or fail), or when its C++ Tick returns Succeeded or Failed. A Task that never finishes keeps its flow waiting.

Task execution flow.

Blueprint Task ​

  1. Create a Blueprint Class and pick Blueprint Base (FPTask_BlueprintBase) as its parent. Name it, for example FPT_OpenDoor.

  2. Add variables for its settings and tick Instance Editable: they appear in Task Details when the Task is selected.

  3. Implement the events you need:

    EventWhenNotes
    Receive SetupOnce per flow executionCache references here.
    Receive EnterThe Task startsReturn true. Returning false stops the flow with an error.
    Receive TickEvery frame while runningCall Finish Task when done.
    Receive ExitThe Task ends, with its resultUnbind events, clear timers.
    Receive Get Runtime DescriptionWhile the in-game overlay shows the TaskAdd lines such as Door: 40% open.
  4. Call Finish Task from Enter for instant Tasks, or from Tick or an event (a timeline finishing, an overlap) for Tasks that take time.

  5. Use Get Flow Pilot Owner Actor, Get Flow Pilot Component and Get World Context to reach the world.

  6. Compile and save. The Task shows up in the Tasks Palette and Add Task menus right away. Set Blueprint Category in Class Settings to choose its Palette category (empty = All).

Pick Parent Class dialog with Blueprint Base (FPTask_BlueprintBase) selected.
Event Graph of a simple Blueprint Task: Receive Enter returning true, and Finish Task (Success) called when a timeline completes.
The Blueprint Task in the Tasks Palette, and its Instance Editable variables in Task Details.

C++ Task ​

Derive from UFlowPilotTask. Category groups the Task in the Palette, and DisplayName is the name users see.

cpp
// Waits until an Actor exists, e.g. one spawned by another flow.
UCLASS(Category="Gameplay", DisplayName="Wait For Actor")
class UFPTask_WaitForActor : public UFlowPilotTask
{
	GENERATED_BODY()

public:
	virtual bool Enter() override;
	virtual EFPTaskResult Tick(float DeltaTime) override;

protected:
	// Actor to wait for: Self, In Level, or found at Runtime by GameplayTag
	UPROPERTY(EditAnywhere, Category="FlowPilot")
	FFlowActorReference ActorReference;
};

bool UFPTask_WaitForActor::Enter()
{
	Super::Enter(); // Always call Super first
	return true;
}

EFPTaskResult UFPTask_WaitForActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	const bool bFound = GetFlowPilotComponent()->FindSingleActor(ActorReference) != nullptr;
	return bFound ? EFPTaskResult::Succeeded : EFPTaskResult::InProgress;
}

Always call Super

Call Super in Enter, Tick and Exit. It tracks the Task state shown by the Tree View, the debugger and the in-game overlay, and breakpoints hook into it.

Optional overrides:

OverrideUse it to
Exit(EFPTaskResult)Clean up delegates and timers.
GetRuntimeDescription(TArray<FString>&)Show live values in the in-game overlay (non-shipping builds).
IsTaskDataValid(FDataValidationContext&)Show a warning icon in the Tree View when settings are missing (editor).
GetBrush()Pick the icon shown in the Tree View and Palette (editor).
ForEachActor(...)Run code on every Actor a Flow Actor Reference resolves to.

Tasks that hold other Tasks derive from UFlowPilotParent, like Sequence and Parallel.

Optional: a custom Task with a validation warning in the Tree View, its IsTaskDataValid message in the tooltip.