FTasks in Unreal Engine 5

Brief overview and simple tests using FTasks in Unreal Engine 5

FTasts Unreal C++ text on slate gradient background
FTasks Unreal C++

Game Engine

Unreal Engine 5.5.3

IDE

Rider 2024.3.5

Project Name

MyProject

OS

macOS Sequoia 15.3.1

Recently I was looking at FTasks in Unreal Engine 5 and they can be a great tool when programming in C++. The official Tasks System documentation can explain it much better than I can, but the Tasks System helps us "execute your gameplay code asynchronously". Similarly, in a previous post about saving and loading game data asynchronously `Async(EAsyncExecution::TaskGraphMainThread, {}) was used to not disrupt the game thread.

Leveraging Epic's FTask A-D example I wanted quickly implement that into an actor. I Simply created a new Unreal class called MyTasksActor and populated it some functions that I'll use in BeginPlay().

MyTasksActor.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyTasksActor.generated.h"

UCLASS()
class MYPROJECT_API AMyTasksActor : public AActor
{
	GENERATED_BODY()

public:
	// Sets default values for this actor's properties
	AMyTasksActor();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:
	UPROPERTY()
	USceneComponent* MyRoot;

	void FunctionA();
	void FunctionB();
	void FunctionC();
	void FunctionD();
};

All the functions simply log out text, this is a very simple example. The actor will already have access to the FTask class via UE::Tasks. Instead of always having to write UE::Tasks::FTask and UE::Tasks::Launch, we can namespace UE:Tasks so we only need to write FTask and Launch.

Similar to the example in the docs I create four FTask variables, A-D, each calling their respective function along with having select prerequisites. If there is a prerequisite then the function can't launch until the prerequisite has completed.

Then I use the FTasks's Wait function to set a bool indicating that all the functions have completed in the allowed timeframe. In this example I gave it a very generous three seconds. Below is the final .cpp file and here is a link to it on GitHub.

MyTasksActor.cpp

#include "MyTasksActor.h"


// Sets default values
AMyTasksActor::AMyTasksActor()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = false;

	MyRoot = CreateDefaultSubobject<USceneComponent>(TEXT("MyRoot"));
#if WITH_EDITORONLY_DATA
	MyRoot->bVisualizeComponent = true;
#endif
	RootComponent = MyRoot;
}

// Called when the game starts or when spawned
void AMyTasksActor::BeginPlay()
{
	Super::BeginPlay();

	{
		using namespace UE::Tasks;
		
		FTask A = Launch(UE_SOURCE_LOCATION, [this]{ FunctionA(); });
		FTask B = Launch(UE_SOURCE_LOCATION, [this]{ FunctionB(); }, A);
		FTask C = Launch(UE_SOURCE_LOCATION, [this]{ FunctionC(); }, B);
		FTask D = Launch(UE_SOURCE_LOCATION, [this]{ FunctionD(); }, Prerequisites(B, C));

		constexpr int32 MyTime = 3;
		bool bAllTasksComplete = D.Wait(FTimespan::FromSeconds(MyTime));

		if (bAllTasksComplete)
		{
			UE_LOG(LogTemp, Warning, TEXT("All Tasks completed within %d seconds"), MyTime);
		}
	}
}

void AMyTasksActor::FunctionA()
{
	UE_LOG(LogTemp, Warning, TEXT("Task A is complete!!!"));
}

void AMyTasksActor::FunctionB()
{
	UE_LOG(LogTemp, Warning, TEXT("Task B is complete!!!"));
}

void AMyTasksActor::FunctionC()
{
	UE_LOG(LogTemp, Warning, TEXT("Task C is complete!!!"));
}

void AMyTasksActor::FunctionD()
{
	UE_LOG(LogTemp, Warning, TEXT("Task D is complete!!!"));
}

I hope to use FTasks in the future, they look to be very helpful.

Comments (0)

Add a Comment

Sign in to comment or like.

Delete Comment

-