저번에 만든 단순하게 왕복하는 액터를 이용하여
타이머를 이용해 액터를 스폰/제거하는 방법을 작성
이전 작업 : https://zerosik00.tistory.com/71
언리얼 c++로 움직이는 액터 구현하기
핵심 함수GetActorLocation() : 현재 엑터의 위치 FVector를 가져오는 함수SetActorLocation() : 현재 액터의 위치를 "변경"하는 함수핵심 함수 목표c++클래스를 생성시작지점과 이동거리, 이동속도를 변수로
zerosik00.tistory.com
목표 기능?

새로 만든 액터는 공간 정보를 가진 액터를 생성하고, 해당 액터는 지정된 시간마다 액터를 스폰시키도록 하려고 함.
SpawnArea.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SpawnArea.generated.h"
class UBoxComponent;
UCLASS()
class HOMEWORK6_API ASpawnArea : public AActor
{
GENERATED_BODY()
private:
FTimerHandle spawnHandler;
public:
ASpawnArea();
UPROPERTY()
UBoxComponent* RootComp;
UPROPERTY(EditAnywhere, Category = "Spawn")
TSubclassOf<AActor> SpawnObjectClass;
void SpawnActor();
protected:
virtual void BeginPlay() override;
virtual void Tick(float DeltaTime) override;
};
"공간"정보가 필요하기 때문에 기존과 달리 RootComponent를 UBoxComponent로 지정함.
일정 시간 주기로 SpawnActor를 실행시킬 FTimerHandle을 하나 생성하고,
스폰시킬 액터를 등록할 SpawnObjectClass 변수를 선언 및 리플렉션에 등록해두었다.
이전에 만든 움직이는 액터는 BP에서 Mash등을 추가 등을 하였기때문에,
기본 클래스는 AActor로 지정해두었다.
구현부:
ASpawnArea::ASpawnArea()
{
PrimaryActorTick.bCanEverTick = false;
RootComp = CreateDefaultSubobject<UBoxComponent>(TEXT("RootBoxComp"));
SetRootComponent(RootComp);
//혹시 모르니 AActor로 설정하여 다른 액터 사용가능하도록 하고, MovingDefaultActor라면 스폰할때 따로 설정
static ConstructorHelpers::FClassFinder<AActor> BPAsset(TEXT("/Game/Blueprint/BP_DefaultMovingActor"));
if (BPAsset.Succeeded())
{
SpawnObjectClass = BPAsset.Class;
}
}
생성자에서는 BoxComponent를 RootComponent로 등록하고,
SpawnObjectClass의 초기값을 BP_DefaultMovingActor로 지정했다. 이전에 만든 클래스를 BP로 감싸둔것,
void ASpawnArea::BeginPlay()
{
Super::BeginPlay();
GetWorldTimerManager().SetTimer(spawnHandler, this, &ASpawnArea::SpawnActor, 3, true, 3);
}
BeginPlay()에서는 만들어둔 FTimerHandler로 타이머를 등록, 3초마다 반복하며 SpawnActor를 호출하도록 한다.
void ASpawnArea::SpawnActor()
{
FVector rVector = UKismetMathLibrary::RandomPointInBoundingBox(RootComp->GetComponentLocation(), RootComp->GetScaledBoxExtent());
AActor* spawnedActorBase = GetWorld()->SpawnActor<AActor>(SpawnObjectClass, FTransform(FRotator(0), rVector, FVector(1)));
ADefaultMovingActor* moveActor = Cast<ADefaultMovingActor>(spawnedActorBase);
if (moveActor) {
moveActor->MoveSpeed = 1000;
moveActor->MaxRange = FVector(0, MAX_int32, 0);
}
}
3초마다 호출될 ASpawnArea()
UKismetMathLibrary::RandomPointInBoundingBox를 이용해 루트컴포넌트의 박스 영역 내 랜덤 포인트 벡터를 가져온다.
RandomPointInBoundingBox는 파라미터로 중심점과 반폭(halfsize)를 받는데 이는 RootComponent로부터 각각
GetComponentLocation, GetScaledBoxExtent함수로부터 가져올 수 있다.
GetScaledBoxExtent는 SceneComponent에 없으니 주의(Scale정보가 있어야하는듯)
좌표를 얻었으니 이제 SpawnActor함수로 새로운 액터를 레벨에 생성.
SpawnActor 의가장 단순한 사용법으로, 생성할 UClass*와 Transform 정보만으로 위치에 스폰시키도록 하였다.
SpawnActor 는 생성된 액터의 포인터를 반환하는데, 우선 이전에 만든 클래스로 캐스팅을 해주고
이동속도와 이동거리를 변경해주도록한다.
이제 액터를 BoundingBox범위내에서 랜덤 생성이 완료되었다.
이대로는 3초마다 액터를 무한히 생성할것이기 때문에, 일정시간후 제거하는 로직을 추가해보자.
private:
FTimerHandle spawnHandler;
FTimerHandle destroyHandler;
TQueue<AActor*> spawnActorQueue;
public:
void RemoveActor();
헤더 내 삭제를 위한 타이머 핸들러, 생성된 오브젝트들을 관리할 TQueue를 추가. 생성한지 오래된 것부터 제거할것이므로 Queue가 가장 적절하다고 생각됨.
제거를 실행하는 RemoveActor함수도 추가.
void ASpawnArea::BeginPlay()
{
Super::BeginPlay();
GetWorldTimerManager().SetTimer(spawnHandler, this, &ASpawnArea::SpawnActor, 3, true, 3);
GetWorldTimerManager().SetTimer(destroyHandler, this, &ASpawnArea::RemoveActor, 3, true, 9);
}
void ASpawnArea::SpawnActor()
{
...
spawnActorQueue.Enqueue(spawnedActorBase);
}
void ASpawnArea::RemoveActor()
{
AActor* deque;
if (spawnActorQueue.Dequeue(deque)) {
deque->Destroy();
}
}
제거 이벤트 타이머를 추가하고, 초기 딜레이를 9로 설정,
이론상 3번째 엑터가 생성될때부터 하나가 생성되고 동시에 하나가 제거될것임.
Queue는 FIFO방식이니 꺼내서 바로 제거하면 됨.
제거는 Actor의 Destroy함수가 있어 간단히 제거가 가능함.
참고자료
Spawning Actors in Unreal Engine | Unreal Engine 5.5 Documentation | Epic Developer Community
Methods of creating new instances of Actors in gameplay code.
dev.epicgames.com
'개발 > 언리얼' 카테고리의 다른 글
| Collision Response, Linetrace (0) | 2026.04.24 |
|---|---|
| Pawn에서 이동 및 회전 직접 구현하기 (0) | 2026.04.14 |
| 언리얼 C++ 펜듈럼 움직임 구현하기 (0) | 2026.04.10 |
| 언리얼 빌드 이해하기(UBT, UHT, CDO, GC) (0) | 2026.04.10 |
| 언리얼 c++로 움직이는 액터 구현하기 (0) | 2026.04.10 |