오늘 6번째 과제 진행 중 캐릭터가 지나갈 수 있는 플랫폼을 구현하였다.
이 플랫폼은 일정 시간마다 스폰하고 사라지는 패턴을 가지고 있다.
해당 액터를 구현하기 위해서는 두개의 클래스를 생성하였다.
하나는 플랫폼 자체 액터이고 다른 하나는 그 액터를 생성해 주는 액터이다.
액터를 다른 액터가 생성해 줌으로서 액터 위치를 명확하게 하기 편하고 스폰하는 액터를 쉽게 변경할 수 있다.

#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SpawnActor_01.generated.h"
UCLASS()
class HOMEWORK_06_UE_API ASpawnActor_01 : public AActor
{
GENERATED_BODY()
public:
ASpawnActor_01();
protected:
FVector StartLocation;
FVector MoveDirection;
UPROPERTY(VisibleAnywhere, BluePrintReadOnly, Category = "SpawnActor_01|Components")
USceneComponent* SceneRoot;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpawnActor_01|Components")
UStaticMeshComponent* StaticMeshComp;
virtual void BeginPlay() override;
FTimerHandle DestroyTimerHandle;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SpawnActor_01|Spawning")
float DestroyTimer = 10;
private:
UFUNCTION()
void DestroySelf();
};
위 코드를 작성하여 플랫폼 액터를 구현하였다.
스태틱 메시 컴포넌트로 스태틱 메시를 추가하였다.
그리고 소멸 시간을 설정한 변수(DestroyTimer)를 입력하였고
소멸되는 함수(DestroySelf())를 선언하였다.
#include "SpawnActor_01.h"
#include "MovingActorSpawner_01.h"
ASpawnActor_01::ASpawnActor_01()
{
PrimaryActorTick.bCanEverTick = false;
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
SetRootComponent(SceneRoot);
StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMeshComp->SetupAttachment(SceneRoot);
}
void ASpawnActor_01::BeginPlay()
{
Super::BeginPlay();
//액터 소멸시간(DestroyTimer)
GetWorld()->GetTimerManager().SetTimerForNextTick([this]()
{
GetWorld()->GetTimerManager().SetTimer(DestroyTimerHandle, this, &ASpawnActor_01::DestroySelf, DestroyTimer, false);
});
}
void ASpawnActor_01::DestroySelf()
{
Destroy();
}
생성자에서 컴포넌트 함수를 작성하고
비긴플레이함수에서 타이머를 통한 액터 소멸 함수를 작성 하였다.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MovingActorSpawner_01.generated.h"
UCLASS()
class HOMEWORK_06_UE_API AMovingActorSpawner_01 : public AActor
{
GENERATED_BODY()
public:
AMovingActorSpawner_01();
protected:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MovingActorSpawner_01|Spawning")
float SpawnTimer = 3;
virtual void BeginPlay() override;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
class UBoxComponent* SpawnVolume;
UPROPERTY(EditAnywhere, Category="MovingActorSpawner_01|Spawning")
TSubclassOf<AActor> BlueprintToSpawn;
private:
UFUNCTION()
void SpawnActor();
FTimerHandle SpawnTimerHandle;
};
#include "MovingActorSpawner_01.h"
#include "Components/BoxComponent.h"
#include "Kismet/GameplayStatics.h"
#include "SpawnActor_01.h"
AMovingActorSpawner_01::AMovingActorSpawner_01()
{
PrimaryActorTick.bCanEverTick = false;
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("DefaultSceneRoot"));
SpawnVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("SpawnVolume"));
SpawnVolume->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
}
void AMovingActorSpawner_01::BeginPlay()
{
Super::BeginPlay();
//액터 생성 시간(SpawnTimer)
GetWorld()->GetTimerManager().SetTimer(
SpawnTimerHandle, this, &AMovingActorSpawner_01::SpawnActor, SpawnTimer, true);
}
void AMovingActorSpawner_01::SpawnActor()
{
FVector SpawnLocation = GetActorLocation() + FVector(0, 0, 0);
FRotator SpawnRotation = FRotator::ZeroRotator;
if (BlueprintToSpawn)
{
GetWorld()->SpawnActor<ASpawnActor_01>(BlueprintToSpawn, SpawnLocation, SpawnRotation);
}
}
콘텐트 브라우저에 생성된 모습

배치한 모습

액터 스폰을 처음 구현해 봤는데 코드를 복잡하게 짠 것 같다. 특히 생성시간과 소멸시간을 각자 다른 클래스에 둠으로서 코드를 수정하기 불편하였다. 해당 코드를 한 클래스에서 관리하여 수정이 용이하게끔 만들어 액터 스폰에 여러 조건을 부여할 수 있도록 해야겠다.
강의 듣기(아이템 생성), 7번째 과제 진행, 6번째 과제 완성