1. 핵심 개념
-
인터페이스 (IItemInterface): 클래스가 반드시 구현해야 할 함수 목록을 정의한 '계약서'입니다. 상속과 달리 구체적인 로직은 포함하지 않고 함수 원형(틀)만 제공하여 클래스 간의 결합도를 낮춤
-
Overlap vs Hit: 아이템 획득처럼 물리적 충돌 없이 영역 진입만 감지할 때는 Overlap을 사용
-
다형성 (Polymorphism): TArray<IItemInterface*>와 같이 인터페이스 포인터로 관리하면 아이템 종류에 상관없이 동일한 함수(ActivateItem)를 호출할 수 있습니다.
인터페이스 사용시 결합도 감소, 확장성 향상, 다형성 극대화가 된다.
필요한 함수 목록만 약속하고, 새로운 아이템을 만들 때 정의된 인터페이스를 구현만 하면 쉽게 편입가능하다.
2. 주요 코드 구조
[Interface] IItemInterface.h
C++
// [cite: 62-76]
class SPARTAPROJECT_API IItemInterface {
GENERATED_BODY()
public:
virtual void OnItemOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, ...) = 0;
virtual void OnItemEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, ...) = 0;
virtual void ActivateItem(AActor* Activator) = 0;
virtual FName GetItemType() const = 0;
};
[Parent Class] ABaseItem.h/cpp
- 모든 아이템의 부모로, USphereComponent(충돌)와 UStaticMeshComponent(외형)를 포함합니다.
- 생성자에서 이벤트 바인딩: OnComponentBeginOverlap.AddDynamic을 통해 충돌 시 OnItemOverlap이 호출되도록 연결합니다.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ItemInterface.h"
#include "BaseItem.generated.h"
class USphereComponent;
UCLASS()
class PJH_ASSIGNMENT8_API ABaseItem : public AActor, public IItemInterface
{
GENERATED_BODY()
public:
ABaseItem();
protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item|Component")
USceneComponent* Scene;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item|Component")
USphereComponent* Collision;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item|Component")
UStaticMeshComponent* StaticMesh;
virtual void OnItemOverlap(AActor* OverlapActor) override;
virtual void OnItemEndOverlap(AActor* OverlapActor) override;
virtual void ActivateItem(AActor* Activator) override;
virtual FName GetItemType() const override;
virtual void DestroyItem();
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item")
FName ItemType;
};
#include "BaseItem.h"
#include "Components/SphereComponent.h"
ABaseItem::ABaseItem()
{
PrimaryActorTick.bCanEverTick = false;
Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
SetRootComponent(Scene);
Collision = CreateDefaultSubobject<USphereComponent>(TEXT("Collision"));
Collision->SetupAttachment(Scene);
StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
StaticMesh->SetupAttachment(Collision);
}
void ABaseItem::OnItemOverlap(AActor* OverlapActor)
{
}
void ABaseItem::OnItemEndOverlap(AActor* OverlapActor)
{
}
void ABaseItem::ActivateItem(AActor* Activator)
{
}
FName ABaseItem::GetItemType() const
{
return ItemType;
}
void ABaseItem::DestroyItem()
{
Destroy();
}
3. 개발 순서 (Workflow)
-
인터페이스 정의: UInterface를 상속받는 인터페이스 클래스 생성 및 순수 가상 함수 선언.
-
부모 클래스 구현: ABaseItem에서 인터페이스를 상속받고 공통 컴포넌트(루트, 콜리전, 메시) 생성.
-
자식 클래스 파생: ACoinItem, AMineItem, AHealingItem 순으로 상속받아 ActivateItem 등을 목적에 맞게 오버라이딩.
- 블루프린트 설정: C++ 클래스 기반 BP 생성 후 스태틱 메시 및 콜리전 프리셋(OverlapAllDynamic) 설정.
자식 클래스 예시
#include "MineItem.h"
AMineItem::AMineItem()
{
ExplosionDelay = 5.0f;
ExplosionRadius = 300.0f;
ExplosionDamage = 30.0f;
ItemType = "Mine";
}
void AMineItem::ActivateItem(AActor* Activator)
{
DestroyItem();
}
#include "HealingItem.h"
AHealingItem::AHealingItem()
{
HealAmount = 20.0f;
ItemType = "Healing";
}
void AHealingItem::ActivateItem(AActor* Activator)
{
DestroyItem();
}