Neste artigo vamos criar a classe TutoProjectCollectable e definir os seus componentes. Esta classe é do tipo Actor e representa um item que pode ser coletado pelo jogador.
No Content Browser, acesse a pasta TutoProject que está dentro da pasta C++ Classes. Clique com o botão direto em um espaço livre e escolha a opção New C++ Class... como mostra a imagem abaixo.
Na próxima tela escolha Actor como classe pai e clique no botão Next.
Na tela seguinte, coloque TutoProjectCollectable no campo Name e clique no botão Create Class.
Vamos usar um componente Static Mesh para representar visualmente esta classe no jogo. O Static Mesh que será utilizado é o SM_Statue com o Material M_Metal_Gold. Eles fazem parte do Starter Content. A aparência do Static Mesh vai ficar assim:
Abra o arquivo TutoProjectCollectable.h. Observe que o código gerado pela Unreal Engine está usando o modificador de acesso public: duas vezes. Este é um código válido mas eu prefiro manter as variáveis e funções públicas em um único local. Copie a declaração da função Tick(float DeltaTime), coloque embaixo do construtor ATutoProjectCollectable() e remova o segundo bloco public:.
Vamos criar dois ponteiros para componentes, um para o Static Mesh Component e outro para um Scene Component. O Scene Component será usado como Root para podermos definir uma posição relativa para o Static Mesh. O bloco public: do TutoProjectCollectable.h vai ficar assim:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TutoProjectCollectable.generated.h"
UCLASS()
class TUTOPROJECT_API ATutoProjectCollectable : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ATutoProjectCollectable();
// Called every frame
virtual void Tick(float DeltaTime) override;
UPROPERTY(VisibleAnywhere)
USceneComponent* RootScene;
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* StaticMesh;
...
Vamos falar sobre a macro UPROPERTY() no próximo artigo.
RootScene = CreateDefaultSubobject<USceneComponent>(TEXT("RootScene"));
RootComponent = RootScene;
A criação do Static Mesh Component também é feita usando a função CreateDefaultSubobject(). O Static Mesh Component é anexado ao Scene Component usando a função SetupAttachment(). Depois é definido a resposta à colisão como Overlap para o Static Mesh não bloquear o movimento do jogador.
StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMesh->SetupAttachment(RootScene);
StaticMesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Overlap);
Se os dois componentes tivessem sido criados em um Blueprint, eles ficariam assim:
Nós criamos o Static Mesh Component, mas agora precisamos definir qual o Static Mesh que ele irá usar. É utilizado uma estrutura chamada FObjectFinder para buscar um arquivo de Static Mesh dentro do projeto. Se a busca for bem sucedida, o Static Mesh será atribuído ao componente.
ConstructorHelpers::FObjectFinder<UStaticMesh> MeshFile(
TEXT("/Game/StarterContent/Props/SM_Statue.SM_Statue"));
if (MeshFile.Succeeded())
{
StaticMesh->SetStaticMesh(MeshFile.Object);
}
// Sets default values
ATutoProjectCollectable::ATutoProjectCollectable()
{
// Set this actor to call Tick() every frame.
PrimaryActorTick.bCanEverTick = true;
RootScene = CreateDefaultSubobject<USceneComponent>(TEXT("RootScene"));
RootComponent = RootScene;
StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMesh->SetupAttachment(RootScene);
StaticMesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Overlap);
ConstructorHelpers::FObjectFinder<UStaticMesh> MeshFile(
TEXT("/Game/StarterContent/Props/SM_Statue.SM_Statue"));
if (MeshFile.Succeeded())
{
StaticMesh->SetStaticMesh(MeshFile.Object);
}
ConstructorHelpers::FObjectFinder<UMaterial> MaterialFile(
TEXT("/Game/StarterContent/Materials/M_Metal_Gold.M_Metal_Gold"));
if (MaterialFile.Succeeded())
{
StaticMesh->SetMaterial(0, MaterialFile.Object);
}
}