domingo, 18 de outubro de 2020

Mostrando mensagens na tela e no log

Quando estamos aprendendo programação ou tentando encontrar um erro no código, é muito útil escrever algumas mensagens na tela ou no log para verificarmos se o código está executando como deveria.

Antes de mostrar as funções das mensagens, vou falar sobre o tipo FString da Unreal Engine. Este tipo é usado para representar uma sequência de caracteres. Usamos o tipo FString no jogo da Parte I para desenhar as informações do jogador na tela usando a classe AHUD como pode ser visto neste artigo:

Classe TutoProjectHUD: Desenhando na tela

A classe FString possui uma função chamada Printf() que constrói uma FString a partir de um texto de formatação e outros parâmetros que são inseridos no texto. O exemplo abaixo mostra o uso de Printf():

FString PlayerInfo = FString::Printf(TEXT("Rank: %d - Name: %s - Health: %f"), 
                                     3, TEXT("Romero"), 0.4);

/*
  A variável PlayerInfo terá este conteúdo:
  "Rank: 3 - Name: Romero - Health: 0.4"
*/

O texto de formatação contém caracteres especiais que começam com % e que serão substituídos pelos valores dos outros parâmetros em sequência. Os caracteres especiais representam diferentes tipos de valores. No exemplo foram usados estes caracteres:

  • %d: Usado para valores inteiros em formato decimal.
  • %s: Usado para strings (sequência de caracteres).
  • %f: Usado para valores do tipo float.

Cuidado ao usar %s com variáveis do tipo FString. Você precisa colocar o operador * antes do nome da variável, como mostra o exemplo abaixo.

FString Name = TEXT("Romero");

FString PlayerName = FString::Printf(TEXT("Player: %s"), *Name);


Para mostrar uma mensagem na tela, você pode usar este código:

if(GEngine)
{
  GEngine->AddOnScreenDebugMessage(-1, 8, FColor::Red, TEXT("Test message!"));
}

Vamos analisar cada parte deste código:

  • GEngine: Ponteiro que representa a Engine. Para usá-lo é preciso adicionar a linha #include "Engine/Engine.h" no início do arquivo cpp.
  • if(GEngine): Antes de usar um ponteiro você deve verificar se ele está válido. Se GEngine for um ponteiro nulo a expressão do if será false e o código dentro do if não será executado. Se GEngine tiver qualquer outro valor, a expressão do if será true e o código será executado.
  • AddOnScreenDebugMessage(): Função da classe UEngine que mostra a mensagem na tela.
  • -1: O nome deste parâmetro é key. Se você colocar um valor positivo, a mensagem anterior com o mesmo key será removida da tela.
  • 8: Este parâmetro indica o tempo em segundos que a mensagem deve ficar visível na tela.
  • FColor::Red : Cor usada na mensagem.
  • TEXT("Test message!") : A mensagem que será escrita na tela. Pode ser uma variável do tipo FString.


O editor da Unreal possui uma janela chamada Output Log que pode ser acessada no menu Window > Developer Tools > Output Log.

Para mostrar uma mensagem no Log, use este código:

UE_LOG(LogTemp, Warning, TEXT("Test message!"));

LogTemp é uma categoria de Log já existente na Unreal. Warning é o nível da mensagem de Log. As mensagens de nível Warning aparecem em amarelo e as de nível Error aparecem em vermelho. O parâmetro de mensagem aceita caracteres especiais da mesma forma que a função Printf()


Exemplo de uso:

Crie uma classe C++ usando Actor como classe pai. Use o nome MsgActor para a nova classe.

Vamos usar um Scene Component como Root Component para que o Actor tenha um Location. No arquivo MsgActor.h adicione um ponteiro para USceneComponent abaixo da declaração do construtor.

public:	
  // Sets default values for this actor's properties
  AMsgActor();
	
  UPROPERTY(VisibleAnywhere)
  USceneComponent* RootScene;

No arquivo MsgActor.cpp, dentro do construtor, será criado uma instância de USceneComponent e armazenado a referência na variável RootScene. Depois o RootScene é definido como RootComponent deste Actor.

AMsgActor::AMsgActor()
{
  // Set this actor to call Tick() every frame.
  PrimaryActorTick.bCanEverTick = true;

  RootScene = CreateDefaultSubobject<USceneComponent>(TEXT("RootScene"));
  RootComponent = RootScene;
}

Ainda no arquivo MsgActor.cpp, coloque este código na função BeginPlay():

void AMsgActor::BeginPlay()
{
  Super::BeginPlay();
    
  FString Message = FString::Printf(TEXT("BeginPlay of %s - Location: %s"), 
                                    *(GetName()), *(GetActorLocation().ToString()) );
  
  if(GEngine)
  {
    GEngine->AddOnScreenDebugMessage(-1, 8, FColor::Red, Message);
  }
  
  UE_LOG(LogTemp, Warning, TEXT("%s"), *Message);  
}

A função GetName() retorna o nome da instância. A função GetActorLocation() retorna um FVector. O tipo FVector possui a função ToString() que converte o conteúdo de um FVector para um FString.

Compile o código e adicione uma instância de MsgActor no nível. Inicie o jogo e veja as mensagens na tela e na janela Output Log como mostra as imagens abaixo. 



Sumário C++