본캠프 85일차_언리얼엔진 게임개발 입문_스파이크 아이템 생성

YU YEON WON·2025년 12월 11일


오늘은 스파이크 트랩 아이템을 생성하였다.

임시로 라바콘을 메시로 선택하여 로직을 구현하였다. 차량 바로 뒤에 스폰이 되는데 스폰시간, 차량으로 부터의 생성 위치 등을 추후 조정해야 할 것 같다.

C++ 클래스인 아이템 베이스를 상속받아 스파이크 아이템을 만들고 스파이크 아이템에 연결되어 스파이크 객체를 스폰할 수 있도록 스파이크 트랩 액터 클래스를 만들었다.

// V12SpikeItem.h

#pragma once

#include "CoreMinimal.h"
#include "Items/V12ItemBase.h"
#include "Items/V12SpikeTrap.h"
#include "V12SpikeItem.generated.h"

/**
 * 
 */
UCLASS()
class V12_THE_GAME_API AV12SpikeItem : public AV12ItemBase
{
	GENERATED_BODY()
	
	AV12SpikeItem()
	{
		ItemName = "Spike Trap";
	}

	virtual void UseItem(AActor* TargetActor) override;

	UPROPERTY(EditDefaultsOnly, Category = "Spike")
	TSubclassOf<AV12SpikeTrap> SpikeTrapClass;

};
// V12SpikeItem.cpp

#include "Items/V12SpikeItem.h"

void AV12SpikeItem::UseItem(AActor* TargetActor)
{
	Super::UseItem(TargetActor);

	UE_LOG(LogTemp, Warning, TEXT("Spkike Trap!"));

	if (!TargetActor) return;

	FVector SpawnLocation = TargetActor->GetActorLocation();
	SpawnLocation -= TargetActor->GetActorForwardVector() * 300.f; // 뒤에 생성

	FRotator Rotation = TargetActor->GetActorRotation();

	GetWorld()->SpawnActor<AV12SpikeTrap>(SpikeTrapClass, SpawnLocation, Rotation);

}

위와 같이 스파이크아이템 클래스를 만들었고

// V12SpikeTrap.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "V12SpikeTrap.generated.h"

UCLASS()
class V12_THE_GAME_API AV12SpikeTrap : public AActor
{
	GENERATED_BODY()
	
public:	
	AV12SpikeTrap();

protected:
	virtual void BeginPlay() override;

public:	
	virtual void Tick(float DeltaTime) override;

private:
	UPROPERTY(EditAnywhere, Category = "Trap")
	float StartZOffset = -80.f; // 처음 땅속 스폰 위치

	UPROPERTY(EditAnywhere, Category = "Trap")
	float RaiseHeight = 80.f; // 올라올 높이

	UPROPERTY(EditAnywhere, Category = "Trap")
	float RaiseDuration = 0.25f; // 상승 시간(0.25초)

	UPROPERTY(EditAnywhere, Category = "Trap")
	float LifeTimeAfterRaise = 5.0f; // 상승 후 유지 시간

	float ElapsedTime = 0.f;
	FVector InitialLocation;
	FVector TargetLocation;

	FTimerHandle RaiseTimer;
	FTimerHandle DestroyTimer;

	void RaiseUpdate(); // 타이머로 상승 업데이트
	void Destroy(); // 타이머로 액터 제거
};
// V12SpikeTrap.cpp

#include "Items/V12SpikeTrap.h"

AV12SpikeTrap::AV12SpikeTrap()
{
	PrimaryActorTick.bCanEverTick = false;
}

void AV12SpikeTrap::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void AV12SpikeTrap::BeginPlay()
{
	Super::BeginPlay();

	// 땅속에서 시작
	InitialLocation = GetActorLocation();
	InitialLocation.Z += StartZOffset;
	SetActorLocation(InitialLocation);	

	// 목표 위치 설정
	TargetLocation = GetActorLocation();
	TargetLocation.Z += RaiseHeight;

	// 0.01초마다 RaiseUpdate 호출
	GetWorld()->GetTimerManager().SetTimer(RaiseTimer, this, &AV12SpikeTrap::RaiseUpdate, 0.01f, true);
}

void AV12SpikeTrap::RaiseUpdate()
{
	ElapsedTime += 0.01f;

	float Alpha = FMath::Clamp(ElapsedTime / RaiseDuration, 0.f, 1.f);
	FVector NewLocation = FMath::Lerp(InitialLocation, TargetLocation, Alpha);
	SetActorLocation(NewLocation);
	if (Alpha >= 1.f)
	{
		// 상승 완료
		GetWorld()->GetTimerManager().ClearTimer(RaiseTimer);

		// 일정 시간 후 액터 제거
		GetWorld()->GetTimerManager().SetTimer(DestroyTimer, this, &AV12SpikeTrap::Destroy, LifeTimeAfterRaise, false);
	}
}

void AV12SpikeTrap::Destroy()
{
	Super::Destroy();
}

위와 같이 스파이크트랩(실제 맵에 스폰되는 액터) 클래스를 만들고 위 스크린샷 처럼 라바콘 메시로 테스트를 진행하였다.

스폰 시간, 스폰 위치 등을 조절하여 효율적인 사용이 가능하게끔 수정해야겠다.

profile
🕹️🎮🍱✈️📸 안녕하세요! 게임개발에 도전하고 있습니다!

0개의 댓글