sexta-feira, 23 de abril de 2021

Funções static e a classe UGameplayStatics

A palavra-chave static em C++ pode ser usada com variáveis, funções e objetos. Neste artigo vamos focar no uso de static ao declarar funções em uma classe.

Quando uma função é declarada como static em uma classe C++, ela possui um escopo de classe. Isto significa que ela é independente das instâncias da classe e pode ser chamada usando apenas o nome da classe e o operador ::.

Consequentemente, uma função static não tem acesso as variáveis das instâncias. As únicas variáveis que ela consegue acessar, são as variáveis que também foram declaradas como static.

O código abaixo mostra um exemplo simples de uma função static que calcula o quadrado de um número.

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

Você não precisa criar uma instância da classe para poder chamar a função static. Assumindo que a função foi criada em uma classe com o nome ATestStatic, a chamada da função Square() pode ser feita assim:  

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

A palavra-chave static é bastante usada na criação de funções utilitárias de gameplay. Um exemplo disso é a classe UGameplayStatics que contém diversas funções static que podem ser chamadas em C++ e em Blueprint.

A UGameplayStatics é uma Blueprint Function Library. Em outro artigo veremos como criar uma Blueprint Function Library.

O código abaixo mostra as declarações de cinco funções da classe UGameplayStatics que são frequentemente usadas.

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

As imagens abaixo mostram os nodes Blueprint equivalentes às funções acima.



Observe que algumas funções possuem como primeiro parâmetro um UObject* WorldContextObject e que este parâmetro não aparece nos nodes Blueprint. O WorldContextObject será o tópico do próximo artigo.  

   

Sumário C++