티스토리 뷰
🟩 오늘의 목표
- IItemInterface의 함수 시그니처를 언리얼 오버랩 이벤트 규격에 맞게 확장한다.
- ABaseItem에서 컴포넌트 구조(Scene → Collision → StaticMesh)를 설정하고 이벤트를 바인딩한다.
- 코인, 힐링, 지뢰 각 아이템의 특성에 맞는 실전 로직(점수 추가, 체력 회복, 지연 폭발)을 완성한다.
🟧 1. 인터페이스 및 부모 클래스 설계
🟦 IItemInterface : 이벤트 바인딩을 위한 규격 수정
- 오버랩 이벤트는 엔진에서 정해진 매개변수 형식이 있다. 이를 인터페이스에도 그대로 반영해야 한다.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "ItemInterface.generated.h"
UINTERFACE(MinimalAPI)
class UItemInterface : public UInterface { GENERATED_BODY() };
class SPARTAPROJECT_API IItemInterface
{
GENERATED_BODY()
public:
// 엔진 오버랩 이벤트와 바인딩하기 위해 UFUNCTION() 필수
UFUNCTION()
virtual void OnItemOverlap(
UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult) = 0;
UFUNCTION()
virtual void OnItemEndOverlap(
UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex) = 0;
virtual void ActivateItem(AActor* Activator) = 0;
virtual FName GetItemType() const = 0;
};
🟦 ABaseItem : 아이템의 물리적 구조와 이벤트 연결
- 생성자에서 컴포넌트를 계층 구조로 배치하고, OverlapAllDynamic 프리셋을 통해 감지 영역을 설정한다.
// BaseItem.cpp 핵심 로직
ABaseItem::ABaseItem()
{
PrimaryActorTick.bCanEverTick = false;
Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
SetRootComponent(Scene);
Collision = CreateDefaultSubobject<USphereComponent>(TEXT("Collision"));
Collision->SetCollisionProfileName(TEXT("OverlapAllDynamic")); // 겹침 감지 설정
Collision->SetupAttachment(Scene);
StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMesh->SetupAttachment(Collision);
// 델리게이트 바인딩: 충돌 시 함수 자동 호출
Collision->OnComponentBeginOverlap.AddDynamic(this, &ABaseItem::OnItemOverlap);
Collision->OnComponentEndOverlap.AddDynamic(this, &ABaseItem::OnItemEndOverlap);
}
void ABaseItem::OnItemOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
// "Player" 태그가 붙은 액터가 들어왔을 때만 실행
if (OtherActor && OtherActor->ActorHasTag("Player"))
{
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Green, TEXT("Item Overlap Detected!"));
ActivateItem(OtherActor); // 실제 아이템 효과 발동
}
}
🟧 2. 아이템별 특화 로직 구현 (주석 내용 반영)
🟦 코인 및 힐링 아이템 : 즉시 발동형
- 획득 즉시 디버그 메시지를 띄우고(이후 실제 수치 증가 로직 추가 가능) 액터를 제거한다.
// ACoinItem::ActivateItem
void ACoinItem::ActivateItem(AActor* Activator)
{
if (Activator && Activator->ActorHasTag("Player"))
{
// 실제 구현: 플레이어의 점수 변수를 PointValue만큼 증가시키는 로직이 들어갈 자리
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Cyan, FString::Printf(TEXT("Player Gained %d Points!"), PointValue));
DestroyItem(); // 획득 후 제거
}
}
// AHealingItem::ActivateItem
void AHealingItem::ActivateItem(AActor* Activator)
{
if (Activator && Activator->ActorHasTag("Player"))
{
// 실제 구현: Activator를 캐릭터로 캐스팅하여 체력을 HealAmount만큼 회복
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Red, FString::Printf(TEXT("Player Healed %d HP!"), HealAmount));
DestroyItem();
}
}
🟦 지뢰 아이템 (AMineItem) : 지연 발동 및 범위 검사
- 가장 핵심적인 부분으로, FTimerHandle을 통한 지연 실행과 GetOverlappingActors를 이용해 범위 내 타격 판정을 구현한다.
// AMineItem.cpp
AMineItem::AMineItem()
{
ExplosionDelay = 5.0f;
ExplosionRadius = 300.0f;
ExplosionDamage = 30;
ItemType = "Mine";
// 폭발 범위를 시각화하거나 계산할 별도의 콜리전
ExplosionCollision = CreateDefaultSubobject<USphereComponent>(TEXT("ExplosionCollision"));
ExplosionCollision->InitSphereRadius(ExplosionRadius);
ExplosionCollision->SetCollisionProfileName(TEXT("OverlapAllDynamic"));
ExplosionCollision->SetupAttachment(Scene);
}
void AMineItem::ActivateItem(AActor* Activator)
{
// 5초(ExplosionDelay) 후 Explode 함수가 실행되도록 타이머 예약
GetWorld()->GetTimerManager().SetTimer(ExplosionTimerHandle, this, &AMineItem::Explode, ExplosionDelay, false);
}
void AMineItem::Explode()
{
TArray<AActor*> OverlappingActors;
ExplosionCollision->GetOverlappingActors(OverlappingActors); // 현재 범위 내 모든 액터 수집
for (AActor* Actor : OverlappingActors)
{
if (Actor && Actor->ActorHasTag("Player"))
{
// 실제 구현: 플레이어에게 ExplosionDamage만큼의 데미지 전달
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Red, FString::Printf(TEXT("BOOM! Player damaged by %d"), ExplosionDamage));
}
}
DestroyItem(); // 폭발 후 지뢰 제거
}
🟧 3. 에디터 설정 및 검증 방법
- 콜리전 프리셋 : 아이템은 보통 OverlapAllDynamic을 사용하여 물리적 저항 없이 겹침만 감지하도록 설정한다.
- 쿼리 전용(Query Only) : 물리적으로 캐릭터를 밀어낼 필요가 없다면 Collision Enabled를 Query Only로 설정하여 CPU 부하를 줄인다.
- 디버그 팁 : 게임 실행 중 Alt + C를 눌러 콜리전 영역이 적절한 크기로 설정되어 있는지 확인한다.
🟧 핵심 요약 및 주의사항
- UFUNCTION()의 중요성 : 델리게이트(AddDynamic)에 등록할 함수는 엔진이 찾을 수 있도록 반드시 UFUNCTION() 매크로가 선언되어 있어야 한다.
- 태그 기반 판정 : ActorHasTag("Player")를 활용하면 복잡한 캐스팅 없이도 대상이 플레이어인지 빠르게 판별할 수 있다.
- 타이머 핸들 : FTimerHandle을 통해 예약된 함수는 액터가 파괴되기 전에 실행되거나, 필요시 ClearTimer로 취소할 수 있도록 관리해야 한다.
'내일배움캠프 Unreal_7기 > 본캠프' 카테고리의 다른 글
| TIL - 45일차 (0) | 2026.01.30 |
|---|---|
| TIL - 44일차 (0) | 2026.01.29 |
| TIL - 42일차 (0) | 2026.01.27 |
| TIL - 41일차 (0) | 2026.01.26 |
| TIL - 40일차 (0) | 2026.01.23 |

