티스토리 뷰

🟩 오늘의 목표

  • 언리얼 엔진에서 인터페이스(Interface)의 개념을 이해하고 상속(Inheritance)과의 차이점을 파악한다.
  • IItemInterface를 정의하여 다양한 아이템들이 공통된 규칙을 따르도록 설계한다.
  • 인터페이스를 활용해 결합도는 낮추고 확장성은 높은 아이템 시스템을 구현한다.

🟧 1. 인터페이스(Interface)의 이해와 필요성

🟦 인터페이스란 무엇인가?

  • 인터페이스는 클래스가 반드시 구현해야 할 함수 목록(계약서)만을 정의한 것이다.
  • 실제 동작 방식은 정의하지 않고 어떤 기능이 반드시 있어야 한다는 틀만 제공한다.

🟦 상속(Inheritance) vs 인터페이스(Interface)

  • 상속은 부모 클래스의 모든 속성과 기능을 물려받아 재사용하는 구조다.
  • 인터페이스는 함수 원형(시그니처)만을 정의하며, 실제 담길 코드는 각 자식 클래스에서 직접 만들어야 한다.
  • 상속은 부모의 구현을 가져다 쓰는 것이고, 인터페이스는 함수의 틀만 빌려 쓰는 차이가 있다.

🟧 2. 인터페이스 정의 및 아이템 부모 클래스 구현

🟦 IItemInterface 정의

  • 언리얼 엔진의 리플렉션 시스템을 위해 UINTERFACE 매크로를 사용하며, 실제 함수는 IItemInterface 클래스 내부에 순수 가상 함수(= 0) 형태로 선언한다.
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "IItemInterface.generated.h"

UINTERFACE(MinimalAPI)
class UItemInterface : public UInterface
{
    GENERATED_BODY()
};

class SPARTAPROJECT_API IItemInterface
{
    GENERATED_BODY()

public:
    virtual void OnItemOverlap(AActor* OverlapActor) = 0;
    virtual void OnItemEndOverlap(AActor* OverlapActor) = 0;
    virtual void ActivateItem(AActor* Activator) = 0;
    virtual FName GetItemType() const = 0;
};

 

🟦 ABaseItem: 인터페이스를 구현한 부모 클래스

  • AActor와 IItemInterface를 동시에 상속받아 모든 아이템의 기본 틀이 되는 부모 클래스를 만든다.
// BaseItem.h
UCLASS()
class SPARTARPROJECT_API ABaseItem : public AActor, public IItemInterface
{
    GENERATED_BODY()

public:    
    ABaseItem();
    
protected:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item")
    FName ItemType;

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

// BaseItem.cpp
ABaseItem::ABaseItem()
{
    PrimaryActorTick.bCanEverTick = false;
}

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. 구체적인 아이템 클래스 확장

인터페이스를 통해 약속된 함수(ActivateItem)를 각 아이템 특성에 맞게 재정의하는 과정이다.

🟦 코인 아이템 계열 (CoinItem, BigCoin, SmallCoin)

  • 코인 계열의 공통 속성인 점수(PointValue)를 관리하는 중간 부모 클래스를 활용한다.
// CoinItem.h
UCLASS()
class SPARTAPROJECT_API ACoinItem : public ABaseItem
{
    GENERATED_BODY()
public:
    ACoinItem();
protected:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item")
    int32 PointValue;
};

// BigCoinItem.h & .cpp (50점)
ABigCoinItem::ABigCoinItem()
{
    PointValue = 50;
    ItemType = "BigCoin";
}
void ABigCoinItem::ActivateItem(AActor* Activator)
{
    DestroyItem();
}

// SmallCoinItem.h & .cpp (10점)
ASmallCoinItem::ASmallCoinItem()
{
    PointValue = 10;
    ItemType = "SmallCoin";
}
void ASmallCoinItem::ActivateItem(AActor* Activator)
{
    DestroyItem();
}

 

🟦 지뢰(Mine) 및 힐링(Healing) 아이템

  • 전혀 다른 동작을 하는 아이템들도 동일한 인터페이스 함수로 제어가 가능하다.
// MineItem.h & .cpp
AMineItem::AMineItem()
{
    ExplosionDelay = 5.0f;
    ExplosionRadius = 300.0f;
    ExplosionDamage = 30.0f;
    ItemType = "Mine";
}
void AMineItem::ActivateItem(AActor* Activator)
{
    DestroyItem();
}

// HealingItem.h & .cpp
AHealingItem::AHealingItem()
{
    HealAmount = 20.0f;
    ItemType = "Healing";
}
void AHealingItem::ActivateItem(AActor* Activator)
{
    DestroyItem();
}

🟧 핵심 요약 및 주의사항

  • 순수 가상 함수 : IItemInterface에서 = 0으로 선언된 함수는 자식 클래스에서 반드시 구현해야 컴파일 오류가 발생하지 않는다.
  • 결합도 감소 : 클래스 간 구체적인 구현을 공유하지 않고 필요한 함수 목록만 약속하므로 의존도가 낮아진다.
  • 다형성 활용 : TArray<IItemInterface*>와 같은 포인터 배열로 관리하면 아이템 종류에 관계없이 동일한 함수를 호출하여 다룰 수 있다.

'내일배움캠프 Unreal_7기 > 본캠프' 카테고리의 다른 글

TIL - 44일차  (0) 2026.01.29
TIL - 43일차  (1) 2026.01.28
TIL - 41일차  (0) 2026.01.26
TIL - 40일차  (0) 2026.01.23
TIL - 39일차  (0) 2026.01.22