segunda-feira, 26 de abril de 2021

Conclusion of Unreal C++ tutorials

This article concludes part III of the Unreal C++ tutorials. The main purpose of this part is to show how C++ and Blueprint can be used together to get the best of both worlds.

The part III project was made using Unreal Engine version 4.26 and is available at this link:


A simple project was created so that you can understand all the concepts of C++ and Blueprint used in this project. When you assimilate the basic blocks of programming, it becomes easier to be able to program your own games and to understand other more complex programming tutorials.

You don't learn to program just by repeating step-by-step instructions. Programming is similar to a puzzle, you need to understand how each piece works to be able to put them together in the correct way to solve a specific problem.

I want to thank the readers, programmers, and instructors who use and recommend my materials. I am very grateful for all the feedback I receive and feel immense satisfaction in knowing that the material I produce has been very useful for the Unreal Engine community.


Table of Contents C++

 

Conclusão dos tutoriais Unreal C++

Este artigo conclui a parte III dos tutoriais de Unreal C++. O principal objetivo desta parte é mostrar como C++ e Blueprint podem ser usados juntos para obter os benefícios dos dois mundos.

O projeto da parte III foi feito utilizando a Unreal Engine versão 4.26 e está disponível neste link:


Foi criado um projeto simples para que você possa compreender todos os conceitos de C++ e Blueprint usados neste projeto. Quando você assimila os blocos básicos da programação, fica mais fácil para conseguir programar seus próprios jogos e para entender outros tutoriais de programação mais complexos.

Você não aprende a programar apenas repetindo instruções passo a passo. Programação é semelhante a um quebra-cabeça, você precisa entender o funcionamento de cada uma das peças para conseguir junta-las da forma correta para resolver um problema específico. 

Quero agradecer aos leitores, programadores e instrutores que usam e recomendam os meus materiais. Sou muito grato por todo o feedback que recebo e sinto uma imensa satisfação em saber que o material que eu produzo tem sido muito útil para a comunidade da Unreal Engine.


Sumário C++

 

domingo, 25 de abril de 2021

Creating a Blueprint Function Library in C++

During the development of a project, you will need to create some functions that are needed in different parts of the project, both in C ++ and in Blueprints. For these cases, you can create a Blueprint Function Library in C++ to gather these functions in one place.

Let's create a simple Blueprint Function Library in our project to show how it works in practice.

In the Content Browser, access the TutoPart3 folder that is inside the C++ Classes folder. Right-click on free space and choose the New C++ Class... option: 


On the next screen, choose the Blueprint Function Libray class as the parent class and click the Next button.


In the Name field, write TutoBPFunctionLibrary. In the Path field, keep the default project folder. Click the Create Class button. 

Our example will contain only one function, but you can create several functions in a Blueprint Function Library, as long as they are all static.

The name of the example function is GetNumberOfInstances. It returns the number of instances that exist at the current level of the class passed as a parameter.

Add the function declaration to the TutoBPFunctionLibrary.h file as shown in the code below. 

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "TutoBPFunctionLibrary.generated.h"


UCLASS()
class TUTOPART3_API UTutoBPFunctionLibrary : public UBlueprintFunctionLibrary
{
  GENERATED_BODY()

  UFUNCTION(BlueprintCallable, Category = TutoBPLibrary, 
            meta = (WorldContext = "WorldContextObject") )
  static int32 GetNumberOfInstances(UObject* WorldContextObject, 
                                    TSubclassOf < AActor > ActorClass );	
};

The first parameter of the function is WorldContextObject which is a reference to the current level. The WorldContext specifier was used to automatically fill it in the Blueprint node, as explained in the previous article.

In the second parameter, a TSubclassOf was used so that only Actor subclasses are accepted.

Add the implementation of the GetNumberOfInstances() function to the TutoBPFunctionLibrary.cpp file. 

#include "TutoBPFunctionLibrary.h"
#include "Kismet/GameplayStatics.h"

int32 UTutoBPFunctionLibrary::GetNumberOfInstances(UObject* WorldContextObject, 
                                                   TSubclassOf < AActor > ActorClass)
{
 TArray< AActor* > InstancesFound;

 UGameplayStatics::GetAllActorsOfClass(WorldContextObject,ActorClass, InstancesFound);
 
 return InstancesFound.Num(); 
}

The GetAllActorsOfClass() function of the UGameplayStatics class was used. This function fills a TArray with the references of the existing instances in the current level of the class passed as a parameter. Our GetNumberOfInstances() function returns the number of elements in the TArray.

Compile the C++ code.

We will use the GetNumberOfInstances() function in Blueprint to see if all the enemy cannons were destroyed. When this occurs, a message will appear on the screen.

Open the Blueprint FirstPersonGameMode in the FirstPersonBP/Blueprints folder. Right-click on the Event Graph, scroll down the list until you find the category Tuto BPLibrary and select the function Get Number Of Instances. 


The image below is the Blueprint node that represents our function. In the Actor Class parameter, select the EnemyCannon class.


In the Event BeginPlay, we will create a Timer that will execute a custom event called CheckCannons once per second. The CheckCannons event calls the Get Number Of Instance function. If the number of instances of EnemyCannon is equal to zero, then the Print String node displays a message on the screen. The Blueprint script must look like this: 


To add the custom event, right-click on the Event Graph and choose the Add Custom Event option.

Compile the Blueprint and start the game. Destroy all the cannons on the level to see if the message is displayed.


Table of Contents C++

 

Criando uma Blueprint Function Library em C++

Durante o desenvolvimento de um projeto você precisará criar algumas funções que são necessárias em diversas partes do projeto, tanto em C++ quanto em Blueprints. Para estes casos, você pode criar uma Blueprint Function Library em C++ para reunir essas funções em um único lugar.

Vamos criar uma Blueprint Function Library simples em nosso projeto para mostrar o funcionamento na prática.

No Content Browser, acesse a pasta TutoPart3 que está dentro da pasta C++ Classes. Clique com o botão direito em um espaço livre e escolha a opção New C++ Class...


Na tela seguinte, escolha a classe Blueprint Function Libray como classe pai e clique no botão Next.


No campo Name coloque TutoBPFunctionLibrary. No campo Path, mantenha a pasta padrão do projeto. Clique no botão Create Class

O nosso exemplo conterá apenas uma função, mas você pode criar várias funções em uma Blueprint Function Library, desde que todas elas sejam static

O nome da função de exemplo é GetNumberOfInstances. Ela retorna o número de instâncias que existem no nível atual da classe passada como parâmetro.

Adicione a declaração da função no arquivo TutoBPFunctionLibrary.h como mostra o código abaixo. 

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "TutoBPFunctionLibrary.generated.h"


UCLASS()
class TUTOPART3_API UTutoBPFunctionLibrary : public UBlueprintFunctionLibrary
{
  GENERATED_BODY()

  UFUNCTION(BlueprintCallable, Category = TutoBPLibrary, 
            meta = (WorldContext = "WorldContextObject") )
  static int32 GetNumberOfInstances(UObject* WorldContextObject, 
                                    TSubclassOf < AActor > ActorClass );	
};

O primeiro parâmetro da função é o WorldContextObject que é uma referência para o nível atual. Foi usado o especificador WorldContext para preenchê-lo automaticamente no node Blueprint, como foi explicado no artigo anterior.

No segundo parâmetro foi usado um TSubclassOf para que sejam aceitas somente subclasses de Actor.

Adicione a implementação da função GetNumberOfInstances() no arquivo TutoBPFunctionLibrary.cpp

#include "TutoBPFunctionLibrary.h"
#include "Kismet/GameplayStatics.h"

int32 UTutoBPFunctionLibrary::GetNumberOfInstances(UObject* WorldContextObject, 
                                                   TSubclassOf < AActor > ActorClass)
{
 TArray< AActor* > InstancesFound;

 UGameplayStatics::GetAllActorsOfClass(WorldContextObject,ActorClass, InstancesFound);
 
 return InstancesFound.Num(); 
}

Foi usada a função GetAllActorsOfClass() da classe UGameplayStatics. Esta função preenche um TArray com as referências das instâncias existentes no nível atual da classe passada como parâmetro. A nossa função GetNumberOfInstances() retorna a quantidade de elementos do TArray.

Compile o código C++.

Vamos usar a função GetNumberOfInstances() em Blueprint para verificar se todos os canhões inimigos foram destruídos. Quando isto ocorrer, será exibida uma mensagem na tela.

Abra o Blueprint FirstPersonGameMode que está na Pasta FirstPersonBP/Blueprints. Clique com o botão direito no Event Graph, role a listagem até encontrar a categoria Tuto BPLibrary e selecione a função Get Number Of Instances


A imagem abaixo é o node Blueprint que representa a nossa função. No parâmetro Actor Class, selecione a classe EnemyCannon.


No Event BeginPlay vamos criar um Timer que vai executar um evento customizado chamado CheckCannons uma vez por segundo. O evento CheckCannons chama a função Get Number Of Instance. Se o número de instâncias de EnemyCannon for igual a zero, então o node Print String exibe uma mensagem na tela. O script Blueprint deve ficar assim: 


Para adicionar o evento customizado, clique com o botão direito no Event Graph e escolha a opção Add Custom Event.

Compile o Blueprint e inicie o jogo. Destrua todos os canhões do nível para ver se a mensagem é exibida.


Sumário C++


sábado, 24 de abril de 2021

Understanding the WorldContextObject

In an Actor class, you can get a World (current level) reference using the GetWorld() function.

However, static functions must receive an UObject as a parameter in order to call its GetWorld() function and obtain the World reference. This parameter is known as WorldContextObject.

There is a specifier of type Metadata called WorldContext that is used to automatically fill in the parameter WorldContextObject when it is called in Blueprint. That way, the WorldContextObject parameter is not even displayed in the Blueprint node. 

The code below shows an example of using the WorldContext specifier in the declaration of the GetPlayerPawn() function of the UGameplayStatics class: 

UFUNCTION(BlueprintPure, Category="Game", 
          meta=(WorldContext="WorldContextObject", 
                UnsafeDuringActorConstruction="true"))
static class APawn* GetPlayerPawn(const UObject* WorldContextObject, 
                                  int32 PlayerIndex);


Note that the Blueprint node of GetPlayerPawn() does not display the WorldContextObject parameter:

 

You must provide a WorldContextObject if you call GetPlayerPawn() in C++. If it is being called from an Actor class, you can pass the this pointer or to make it clearer you can pass the return of the GetWorld() function as shown in this example:

APawn* PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);


Now that we know what static functions are and understand the use of WorldContextObject, we are ready to create our own Blueprint Function Library in the next article.


Table of Contents C++ 

 

Entendendo o WorldContextObject

Em uma classe do tipo Actor, você consegue pegar uma referência do World (nível atual) usando a função GetWorld().

Entretanto, as funções static precisam receber por parâmetro um UObject para poder chamar a função GetWorld() dele e obter a referência do World. Este parâmetro é conhecido como WorldContextObject.

Existe um especificador do tipo Metadata chamado WorldContext que é usado para preencher automaticamente o parâmetro WorldContextObject quando é chamado em Blueprint. Dessa forma, o parâmetro WorldContextObject nem é exibido no node Blueprint.   

O código abaixo mostra um exemplo de uso do especificador WorldContext na declaração da função GetPlayerPawn() da classe UGameplayStatics

UFUNCTION(BlueprintPure, Category="Game", 
          meta=(WorldContext="WorldContextObject", 
                UnsafeDuringActorConstruction="true"))
static class APawn* GetPlayerPawn(const UObject* WorldContextObject, 
                                  int32 PlayerIndex);


Veja que o node Blueprint do GetPlayerPawn() não exibe o parâmetro WorldContextObject:

 

É preciso fornecer um WorldContextObject se chamar o GetPlayerPawn() em C++. Se estiver sendo chamado a partir de uma classe do tipo Actor, você pode passar o ponteiro this ou para ficar mais claro pode passar o retorno da função GetWorld() como mostra este exemplo:

APawn* PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);


Agora que já sabemos o que são funções static e entendemos o uso do WorldContextObject, estamos prontos para criar a nossa própria Blueprint Function Library no próximo artigo.


Sumário C++ 


sexta-feira, 23 de abril de 2021

Static functions and the UGameplayStatics class

The static keyword in C++ can be used with variables, functions, and objects. In this article, we will focus on the use of static when declaring functions in a class.

When a function is declared as static in a C++ class, it has a class scope. This means that it is independent of the instances of the class and can be called using only the name of the class and the :: operator.

Consequently, a static function does not have access to the instance variables. The only variables it can access are the variables that have also been declared as static.

The code below shows a simple example of a static function that squares a number.

static float Square(float value)
{
  return value * value;
}

You do not need to create an instance of the class in order to be able to call the static function. Assuming that the function was created in a class named ATestStatic, the call to the Square() function can be done as follows:

float result = ATestStatic::Square(4.5f);

The keyword static is widely used in the creation of gameplay utility functions. An example of this is the UGameplayStatics class which contains several static functions that can be called in C++ and Blueprint.

UGameplayStatics is a Blueprint Function Library. In another article, we will see how to create a Blueprint Function Library.

The code below shows the declarations of five functions of the UGameplayStatics class that are frequently used.

UFUNCTION(BlueprintPure, Category="Game", 
          meta=(WorldContext="WorldContextObject", 
                UnsafeDuringActorConstruction="true"))
static class APawn* GetPlayerPawn(const UObject* WorldContextObject, 
                                  int32 PlayerIndex);

UFUNCTION(BlueprintPure, Category="Game", 
          meta=(WorldContext="WorldContextObject", 
                UnsafeDuringActorConstruction="true"))
static class APlayerController* GetPlayerController(
                                   const UObject* WorldContextObject, 
                                   int32 PlayerIndex);

UFUNCTION(BlueprintCallable, 
          meta=(WorldContext="WorldContextObject", 
                AdvancedDisplay = "2", 
                DisplayName = "Open Level (by Name)"), 
          Category="Game")
static void OpenLevel(const UObject* WorldContextObject, FName LevelName, 
               bool bAbsolute = true, FString Options = FString(TEXT("")));

UFUNCTION(BlueprintCallable, Category="Audio", 
          meta=(WorldContext="WorldContextObject", 
                AdvancedDisplay = "3", 
                UnsafeDuringActorConstruction = "true", 
                Keywords = "play"))
static void PlaySoundAtLocation(const UObject* WorldContextObject, 
               USoundBase* Sound, FVector Location, FRotator Rotation, 
               float VolumeMultiplier = 1.f, float PitchMultiplier = 1.f, 
               float StartTime = 0.f, 
               class USoundAttenuation* AttenuationSettings = nullptr, 
               USoundConcurrency* ConcurrencySettings = nullptr, 
               AActor* OwningActor = nullptr);

UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="Game|Damage")
static float ApplyDamage(AActor* DamagedActor, float BaseDamage, 
               AController* EventInstigator, AActor* DamageCauser, 
               TSubclassOf<class UDamageType> DamageTypeClass);

The images below show the Blueprint nodes equivalent to the above functions.



Note that some functions have a UObject* WorldContextObject as their first parameter and that this parameter does not appear in Blueprint nodes. The WorldContextObject will be the topic of the next article.


Table of Contents C++