sábado, 19 de dezembro de 2020

TArray: Arrays em C++

TArray é um tipo de container que armazena um ou mais elementos de um mesmo tipo. Container é um tipo de classe cujas instâncias são coleções de outros objetos. Outros exemplos de container em Unreal C++ são TSet e TMap, que serão vistos nos próximos artigos.

Uma forma simples de entender o conceito de Array é visualizar no editor da Unreal. Este código cria um Array com o nome TownNames para armazenar elementos do tipo FString

UPROPERTY(EditAnywhere, Category=ArrayTown)
TArray<FString> TownNames;

A imagem abaixo mostra o Array no editor. Você pode adicionar elementos clicando no ícone +. Os números do lado esquerdo são os índices dos elementos do Array. O primeiro elemento de um Array possui o índice zero.


Duas função podem ser usadas para adicionar elementos em um Array usando C++. A função Add() adiciona elementos no final do Array e a função Insert() adiciona um elemento no índice passado como parâmetro.

TownNames.Add(TEXT("Tarrin"));

TownNames.Insert(TEXT("Pitmerden"), 2);

Você pode ler e modificar elementos de um Array usando o operador [] e o índice do elemento.

FString FirstTown = TownNames[0];

TownNames[3] = TEXT("Penkurth");

Cuidado, se você usar um índice menor que 0 ou igual ou maior que o número de elementos de um Array, irá gerar um erro em tempo de execução.

Para saber o número de elementos de um Array, use a função Num():

int32 NumberOfElements = TownNames.Num();


Exemplo de uso:

Vamos criar um Array para guardar referências de instâncias de Actor e depois escrever na tela os nomes das instâncias que foram adicionadas ao Array. 

Crie uma classe C++ com o nome TestTArray usando como classe pai a classe Actor. No arquivo TestTArray.h, adicione a declaração dos componentes e do TArray como mostra este código:

#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;

};

Este é o conteúdo do arquivo 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);
}

Na função BeginPlay() usamos um ranged-based for loop para iterar nos elementos do Array e escrever na tela o nome de cada instância. 

Compile o código C++ e adicione uma instância de TestTArray no nível. Você pode adicionar elementos no Array usando a aba Details da instância.


Inicie o jogo e veja na tela os nomes das instâncias de Actor:


Sumário C++