TArray is a type of container that stores one or more elements of the same type. Container is a type of class whose instances are collections of other objects. Other examples of containers in Unreal C++ are TSet and TMap, which will be seen in the next articles.
A simple way to understand the concept of Array is to view it in the Unreal editor. This code creates an Array with the name TownNames to store elements of type FString.
UPROPERTY(EditAnywhere, Category=ArrayTown)
TArray<FString> TownNames;
The image below shows the Array in the editor. You can add elements by clicking on the + icon. The numbers on the left side are the indexes of the elements of the Array. The first element of an Array has a zero index.
Two functions can be used to add elements to an Array using C++. The Add() function adds elements at the end of the Array and the Insert() function adds an element at the index passed as a parameter.
TownNames.Add(TEXT("Tarrin"));
TownNames.Insert(TEXT("Pitmerden"), 2);
You can read and modify elements of an Array using the operator [] and the element's index.
FString FirstTown = TownNames[0];
TownNames[3] = TEXT("Penkurth");
Be careful, if you use an index less than 0 or equal to or greater than the number of elements in an Array, it will generate a runtime error.
To find out the number of elements in an Array, use the Num() function:
int32 NumberOfElements = TownNames.Num();
Example usage:
We will create an Array to store references to Actor instances and then write on the screen the names of the instances that have been added to the Array.
Create a C++ class with the name TestTArray using the Actor class as the parent class. In the TestTArray.h file, add the declaration of the components and of the TArray as shown in this code:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TestTArray.generated.h"
UCLASS()
class TUTOPROJECT_API ATestTArray : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ATestTArray();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
UPROPERTY(VisibleAnywhere)
USceneComponent* RootScene;
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* StaticMesh;
UPROPERTY(EditAnywhere, Category=ArrayExample)
TArray<AActor*> SelectedActors;
};
This is the contents of the file TestTArray.cpp:
#include "TestTArray.h"
ATestTArray::ATestTArray()
{
// Set this actor to call Tick() every frame.
PrimaryActorTick.bCanEverTick = true;
RootScene = CreateDefaultSubobject<USceneComponent>("RootScene");
RootComponent = RootScene;
StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>("StaticMesh");
StaticMesh->SetupAttachment(RootScene);
}
// Called when the game starts or when spawned
void ATestTArray::BeginPlay()
{
Super::BeginPlay();
FString Message;
if(SelectedActors.Num() > 0)
{
Message = FString::Printf(TEXT("Number of elements in the array: %d"),
SelectedActors.Num());
if(GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Red, Message);
Message = FString::Printf(TEXT("--- Selected Actors ---"));
GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Red, Message);
for (AActor* ActorInstance : SelectedActors)
{
Message = FString::Printf(TEXT("Instance Name: %s"),
*(ActorInstance->GetName()));
GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Red, Message);
}
}
}
}
// Called every frame
void ATestTArray::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
In the BeginPlay() function we use a ranged-based for loop to iterate over the elements of the Array and write the name of each instance on the screen.
Compile the C++ code and add an instance of TestTArray at the level. You can add elements to the Array using the Details tab of the instance.
Start the game and see the names of the Actor instances on the screen: