Blog

ENGINEERING NOTE

[Unreal Engine] 인터페이스

해당 포스팅은 Stuart Butler , Tom Oliver의 Game Development Patterns with Unreal Engine 5를 바탕으로 작성한 내용입니다.인터페이스는 서로 다른 클래스가 공통적으로 제공해야 하는 동작(함수) 의 "계약(contra

Unreal Engine
해당 포스팅은 Stuart Butler , Tom Oliver의 Game Development Patterns with Unreal Engine 5를 바탕으로 작성한 내용입니다.

인터페이스(Interface)란 무엇인가?

인터페이스는 서로 다른 클래스가 공통적으로 제공해야 하는 동작(함수) 의 "계약(contract)"을 정의한다.

인터페이스는 구현을 가지지 않고 함수 시그니처만 정의한다. 어떤 객체가 인터페이스를 구현하면, 해당 객체는 인터페이스에 정의된 동작을 반드시 제공한다.

인터페이스의 장점

  • 느슨한 결합(Loose Coupling)을 유지한다.
  • 다형성(Polymorphism)을 확보한다.
  • 블루프린트와 C++ 간 공통 구조를 제공한다.

인터페이스의 단점 / 주의점

* 상태(변수)를 포함하지 않는다. * 데이터 전달은 함수 매개변수로만 처리한다. * 매우 자주 호출되는 반복 로직에서는 미세한 비용이 발생한다.

사용 목적

* 여러 클래스가 동일한 동작을 처리해야 할 때 활용한다. * 타입 정보를 몰라도 동작만 호출하고 싶을 때 사용한다.


언제 인터페이스를 사용해야 하는가?

* 문, 상자, NPC 등 다양한 클래스가 Interact 같은 동일한 상호작용 기능을 제공해야 할 때 * 구체 클래스를 몰라도 메시지만 전달하고 싶을 때 * 유지보수성과 확장성을 고려하여 결합도를 낮추고 싶을 때

상태 전달이 잦다면 인터페이스보다는 이벤트/디스패처나 직접 참조가 적합할 수 있다.


블루프린트에서 인터페이스

인터페이스 생성

먼저 콘텐츠 브라우저 → Blueprint Interface 생성한다.

우선 예시로 Interact라는 함수를 만들었다.

클래스에 인터페이스 적용

블루프린트 클래스 → Class SettingsImplemented Interfaces에서 추가한다.

인터페이스 함수는 기본적으로 이벤트 형태로 표시되며 구현할 수 있다. 인터페이스에서 변수를 추가하면 리턴 노드가 포함된 함수로도 만들 수 있다.

인터페이스 호출

이제 구현된 인터페이스 함수나 이벤트를 다른 액터에서 호출할 수 있다.


C++에서의 인터페이스

인터페이스 선언 구조

언리얼 C++ 인터페이스는 두 파트로 구성된다.

* UINTERFACE 클래스: UObject 시스템용 메타 계층 * IInterface 클래스: 실제 함수 계약을 정의한다.

헤더 선언 예시

cpp
#pragma once

#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "InteractInterface.generated.h"

// 언리얼 리플렉션용 클래스 (구현 없음)
UINTERFACE(MinimalAPI, Blueprintable)
class UInteractInterface : public UInterface
{
    GENERATED_BODY()
};

// 실제 인터페이스 (함수 계약 정의)
class IInteractInterface
{
    GENERATED_BODY()

public:
    // 블루프린트와 C++ 둘 다에서 구현 가능하게 함
    UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category="Interaction")
    void Interact(AActor* Interactor);
};

구현 예시

cpp
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "InteractInterface.h"
#include "Door.generated.h"

UCLASS()
class ADoor : public AActor, public IInteractInterface
{
    GENERATED_BODY()

public:
    // BlueprintNativeEvent를 구현할 때 반드시 _Implementation 필요
    virtual void Interact_Implementation(AActor* Interactor) override;
};

인터페이스 호출

cpp
void AMyCharacter::TryInteract()
{
    FHitResult Hit;
    FVector Start = FollowCamera->GetComponentLocation();
    FVector End   = Start + FollowCamera->GetForwardVector() * 300.0f;

    FCollisionQueryParams Params;
    Params.AddIgnoredActor(this);

    if (GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Visibility, Params))
    {
        AActor* HitActor = Hit.GetActor();
        if (HitActor && HitActor->GetClass()->ImplementsInterface(UInteractInterface::StaticClass()))
        {
            // 인터페이스 함수 호출
            IInteractInterface::Execute_Interact(HitActor, this);
        }
    }
}
더 자세한 내용은 공식 문서의 언리얼 인터페이스를 읽어보면 도움이 된다.