terça-feira, 9 de março de 2021

PlayerProjectile: Criando uma classe base em C++

Em um projeto que envolve Blueprint e C++, um workflow comum é criar uma classe base em C++ com variáveis e funções e depois criar os Blueprints filhos que definirão os Assets utilizados e que podem definir outras variáveis e funções específicas para o Blueprint.

Uma classe base também é chamada de classe pai ou superclasse.

Neste artigo vamos implementar a classe base PlayerProjectile em C++. Esta classe representa o projétil disparado pelo jogador. No projeto de exemplo, o jogador possui três tipos de projéteis que são representados por Blueprint filhos de PlayerProjectile

Clique no menu File do editor da Unreal e escolha a opção New C++ Class... como mostra a imagem abaixo.


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

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


Como esta é a primeira classe C++ deste projeto Blueprint, o editor da Unreal fará a conversão para um projeto C++.

A classe PlayerProjectile usará três componentes:

  • USphereComponent: É usado como componente Root e para o teste de colisão.
  • UStaticMeshComponent: Contém o Static Mesh que representará visualmente o Ator.
  • UProjectileMovementComponent: Componente usado para movimentar o Ator. 
 

Adicione a declaração dos componentes no arquivo PlayerProjectile.h que deve ficar com este conteúdo:  

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "PlayerProjectile.generated.h"

UCLASS()
class TUTOPART3_API APlayerProjectile : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	APlayerProjectile();

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, BlueprintReadOnly)
	UStaticMeshComponent* StaticMesh;
	
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
	class USphereComponent* CollisionComponent;
	
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)	
	class UProjectileMovementComponent* ProjectileMovement;

};

No arquivo PlayerProjectile.cpp, temos a inicialização dos três componentes feita no construtor. Não esqueça de adicionar as linhas #include

#include "PlayerProjectile.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Engine/CollisionProfile.h"
#include "Components/SphereComponent.h"

// Sets default values
APlayerProjectile::APlayerProjectile()
{
  PrimaryActorTick.bCanEverTick = true;

  InitialLifeSpan = 10.f;

  CollisionComponent = CreateDefaultSubobject<USphereComponent>(
                                             TEXT("CollisionComponent"));
  RootComponent = CollisionComponent;
  CollisionComponent->InitSphereRadius(20.f);
  CollisionComponent->SetCollisionProfileName(
                           UCollisionProfile::BlockAllDynamic_ProfileName);

  StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
  StaticMesh->SetupAttachment(CollisionComponent);
	
  ProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>(
                                             TEXT("ProjectileMovement"));
  ProjectileMovement->InitialSpeed = 3000.f;
  ProjectileMovement->MaxSpeed = 3000.f;
  ProjectileMovement->ProjectileGravityScale = 0.f;
}

// Called when the game starts or when spawned
void APlayerProjectile::BeginPlay()
{
  Super::BeginPlay();
}

// Called every frame
void APlayerProjectile::Tick(float DeltaTime)
{
  Super::Tick(DeltaTime);
}

Compile o código C++.

Os valores iniciais atribuídos aos componentes poderão ser modificados nos Blueprints filhos.

Observe que não definimos o Asset usado pelo Static Mesh. Devemos evitar referenciar pastas e Assets direto no código C++, porque se o Asset for renomeado ou movido para outra pasta, provocará um erro no código C++, que precisará ser atualizado e compilado novamente.

Este problema não ocorre em Blueprint. O editor automaticamente atualiza as referências de um Asset em Blueprints quando ele é renomeado ou movido para outra pasta.  


Sumário C++