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

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();
}
위와 같이 스파이크트랩(실제 맵에 스폰되는 액터) 클래스를 만들고 위 스크린샷 처럼 라바콘 메시로 테스트를 진행하였다.
스폰 시간, 스폰 위치 등을 조절하여 효율적인 사용이 가능하게끔 수정해야겠다.