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.