카테고리 없음

언리얼C++) 인터페이스 기반 아이템 설계

eclipse2 2026. 4. 16. 19:14

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();
}