A classe AActor é uma subclasse de UObject e representa os objetos de gameplay que podem ser adicionados ao nível. As classes que herdam de AActor tem o prefixo A.
Uma parte da funcionalidade de um AActor é obtida com o uso de componentes. As informações de translação, rotação e escala de um AActor são obtidas a partir do seu RootComponent. Então, um AActor precisa ter pelo menos um USceneComponent que seja definido como o seu RootComponent.
Você pode usar o editor de nível para adicionar Atores e eles podem ser criados em tempo de execução usando a função SpawnActor(). Existem diversas versões da função SpawnActor(), o exemplo abaixo mostra uma delas, assumindo que a classe AActorChild é uma subclasse de AActor:
FVector SpawnLocation = FVector(0.0f, 0.0f, 0.0f);
FRotator SpawnRotation = FRotator(0.0f, 0.0f, 0.0f);
GetWorld()->SpawnActor<AActorChild>(AActorChild::StaticClass(),
SpawnLocation, SpawnRotation );
Quando quiser destruir uma instância de AActor, pode usar a função Destroy() da classe AActor. Você também pode usar a função SetLifeSpan() para indicar o tempo em segundos que um AActor deve ficar vivo. Quando este tempo acabar, o AActor será destruído automaticamente.
Exemplo de uso:
Para este exemplo será necessário um projeto com o Starter Content.
Vamos criar dois Atores, o CannonActor e o BulletActor. O CannonActor criará uma instância de BulletActor por segundo. O BulletActor se moverá em frente e será destruído após 15 segundos.
Crie uma classe C++ com o nome BulletActor usando como classe pai a classe Actor. O arquivo BulletActor.h deve ficar com este conteúdo:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "BulletActor.generated.h"
UCLASS()
class TUTOPROJECT_API ABulletActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ABulletActor();
// Called every frame
virtual void Tick(float DeltaTime) override;
virtual void NotifyActorBeginOverlap(AActor* OtherActor) override;
UPROPERTY(VisibleAnywhere)
USceneComponent* RootScene;
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* StaticMesh;
UPROPERTY(VisibleAnywhere)
class UProjectileMovementComponent* ProjectileMovement;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
};
A classe BulletActor possui três componentes:
- USceneComponent: Possui um Transform e será usado como componente Root.
- UStaticMeshComponent: Contém o Static Mesh que representará visualmente o Ator.
- UProjectileMovementComponent: Componente usado para movimentar o Ator. Observe que foi colocado a palavra class antes da definição da variável. Será necessário adicionar o #include desta classe no arquivo cpp.
No arquivo BulletActor.cpp, a definição do construtor fica assim:
#include "BulletActor.h"
#include "GameFramework/ProjectileMovementComponent.h"
// Sets default values
ABulletActor::ABulletActor()
{
// 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/Shapes/Shape_Sphere.Shape_Sphere"));
if (MeshFile.Succeeded())
{
StaticMesh->SetStaticMesh(MeshFile.Object);
}
ProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>(
TEXT("ProjectileMovementComp") );
ProjectileMovement->UpdatedComponent = StaticMesh;
ProjectileMovement->InitialSpeed = 500.f;
ProjectileMovement->MaxSpeed = 500.f;
ProjectileMovement->ProjectileGravityScale = 0.f;
}
No construtor é feita a inicialização dos três componentes. O BulletActor usa o Static Mesh de uma esfera e se moverá em uma velocidade de 500 unidades por segundo sem gravidade.
As outras funções que precisam ser implementadas em BulletActor.cpp são estas:
void ABulletActor::BeginPlay()
{
Super::BeginPlay();
SetLifeSpan(15.f);
}
void ABulletActor::NotifyActorBeginOverlap(AActor* OtherActor)
{
Super::NotifyActorBeginOverlap(OtherActor);
Destroy();
}
Na função BeginPlay() é definido que a instância de ABulletActor será destruída após 15 segundos. A função NotifyActorBeginOverlap() é chamada quando a instância sobrepor outro Ator. Em nosso exemplo a instância de ABulletActor é destruída se isso acontecer.
Agora crie uma classe C++ com o nome CannonActor usando como classe pai a classe Actor. O arquivo CannonActor.h deve ficar com este conteúdo:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "CannonActor.generated.h"
UCLASS()
class TUTOPROJECT_API ACannonActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ACannonActor();
// Called every frame
virtual void Tick(float DeltaTime) override;
UPROPERTY(VisibleAnywhere)
USceneComponent* RootScene;
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* StaticMesh;
FTimerHandle ShotTimerHandle;
void ShootCannon();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
};
A classe ACannonActor possui um Timer que chama a função ShootCannon uma vez por segundo para criar uma instância de ABulletActor.
Este é o construtor que está no arquivo CannonActor.cpp:
#include "CannonActor.h"
#include "BulletActor.h"
// Sets default values
ACannonActor::ACannonActor()
{
// 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);
ConstructorHelpers::FObjectFinder<UStaticMesh> MeshFile(
TEXT("/Game/StarterContent/Props/SM_MatPreviewMesh_02.SM_MatPreviewMesh_02"));
if (MeshFile.Succeeded())
{
StaticMesh->SetStaticMesh(MeshFile.Object);
}
}
O Timer é configurado na função BeginPlay(). A função ShootCannon() usa a função SpawnActor() para criar uma instância de ABulletActor em uma posição e uma rotação baseados no canhão:
void ACannonActor::BeginPlay()
{
Super::BeginPlay();
GetWorldTimerManager().SetTimer(ShotTimerHandle, this,
&ACannonActor::ShootCannon, 1.f, true);
}
void ACannonActor::ShootCannon()
{
FRotator SpawnRotation = GetActorRotation();
FVector SpawnLocation = GetActorLocation()
+ SpawnRotation.RotateVector(FVector(180.0f, 0.0f, 180.0f));
GetWorld()->SpawnActor<ABulletActor>(ABulletActor::StaticClass(),
SpawnLocation, SpawnRotation );
}
Compile o código C++ e adicione uma instância de CannonActor no nível. Inicie o jogo e veja o canhão disparando as balas: