Skip to content

UE5 C++ UInterface & 인터페이스

C++ 순수 가상 함수로도 인터페이스를 구현할 수 있지만, UE의 UInterface는 다음 장점을 추가로 제공합니다.

기능일반 C++ 인터페이스UInterface
Blueprint 연동불가BlueprintImplementableEvent / BlueprintNativeEvent
런타임 타입 확인dynamic_cast (RTTI)Implements<T>() (리플렉션)
Soft Reference 지원불가TScriptInterface<T>
에디터 노출불가UPROPERTY(EditAnywhere)

UE 인터페이스는 항상 두 클래스 쌍으로 선언됩니다.

  • UMyInterface: UInterface를 상속, 리플렉션 정보 담당 (비어 있어도 됨)
  • IMyInterface: 실제 인터페이스 함수 선언
InteractableInterface.h
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "InteractableInterface.generated.h"
// UInterface 클래스 — 리플렉션 등록용, 함수 선언 없음
UINTERFACE(MinimalAPI, BlueprintType)
class UInteractableInterface : public UInterface
{
GENERATED_BODY()
};
// 실제 인터페이스 — 함수를 여기에 선언
class MYGAME_API IInteractableInterface
{
GENERATED_BODY()
public:
// C++ 순수 가상 함수 (C++에서 반드시 구현)
virtual FString GetInteractionPrompt() const = 0;
// Blueprint에서 재정의 가능 (C++ 기본 구현 있음)
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Interaction")
void Interact(AActor* Interactor);
virtual void Interact_Implementation(AActor* Interactor) {}
// Blueprint에서만 구현 (C++는 선언만)
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "Interaction")
void OnInteractionFailed(AActor* Interactor);
// 인터페이스 함수 — 기본 구현 있는 일반 가상 함수
virtual bool CanInteract(AActor* Interactor) const { return true; }
};
지정자의미
MinimalAPI최소 노출 (엔진 내부 규칙)
BlueprintTypeBlueprint에서 이 인터페이스 타입을 변수로 사용 가능
BlueprintableBlueprint 클래스가 이 인터페이스를 구현 가능
NotBlueprintableC++만 구현 가능 (기본값 아닐 때 명시)

PickupItem.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "InteractableInterface.h"
#include "PickupItem.generated.h"
UCLASS()
class MYGAME_API APickupItem : public AActor, public IInteractableInterface
{
GENERATED_BODY()
public:
// C++ 순수 가상 함수 구현 (필수)
virtual FString GetInteractionPrompt() const override;
// BlueprintNativeEvent 구현 — _Implementation 접미사 필수
virtual void Interact_Implementation(AActor* Interactor) override;
// CanInteract 재정의
virtual bool CanInteract(AActor* Interactor) const override;
private:
UPROPERTY(EditDefaultsOnly, Category = "Pickup")
FName ItemID;
UPROPERTY(EditDefaultsOnly, Category = "Pickup")
bool bIsEnabled = true;
};
PickupItem.cpp
#include "PickupItem.h"
#include "GameFramework/Character.h"
FString APickupItem::GetInteractionPrompt() const
{
return FString::Printf(TEXT("E 키를 눌러 %s 줍기"), *ItemID.ToString());
}
void APickupItem::Interact_Implementation(AActor* Interactor)
{
// Blueprint에서 재정의하지 않으면 이 코드가 실행됨
UE_LOG(LogTemp, Log, TEXT("Picking up item: %s"), *ItemID.ToString());
Destroy(); // 아이템 제거
}
bool APickupItem::CanInteract(AActor* Interactor) const
{
return bIsEnabled && IsValid(Interactor);
}

3.1 Cast<> 방식 (C++ only 인터페이스)

Section titled “3.1 Cast<> 방식 (C++ only 인터페이스)”
void APlayerCharacter::TryInteract(AActor* Target)
{
// Cast로 인터페이스 포인터 획득
IInteractableInterface* Interactable = Cast<IInteractableInterface>(Target);
if (Interactable)
{
if (Interactable->CanInteract(this))
{
FString Prompt = Interactable->GetInteractionPrompt();
UE_LOG(LogTemp, Log, TEXT("Prompt: %s"), *Prompt);
}
}
}

3.2 Execute_ 방식 (Blueprint 연동 함수 필수)

Section titled “3.2 Execute_ 방식 (Blueprint 연동 함수 필수)”

BlueprintNativeEvent / BlueprintImplementableEvent로 선언된 함수는 Cast 대신 Execute_ 정적 함수를 사용해야 Blueprint 구현이 올바르게 호출됩니다.

void APlayerCharacter::TryInteract(AActor* Target)
{
// Implements<> — 인터페이스 구현 여부 확인 (Blueprint 구현 포함)
if (Target->Implements<UInteractableInterface>())
{
// Execute_ 접두사 정적 함수 — Blueprint/C++ 구현 모두 올바르게 호출
IInteractableInterface::Execute_Interact(Target, this);
}
}
호출 방식Blueprint 구현 호출C++ 구현 호출권장
Cast<IMyInterface>(Actor)->Func()XOC++ only 함수
IMyInterface::Execute_Func(Actor)OOBlueprintNativeEvent / ImplementableEvent
Actor->Implements<UMyInterface>()확인용확인용구현 여부 체크

4. TScriptInterface — UPROPERTY에서 인터페이스 저장

Section titled “4. TScriptInterface — UPROPERTY에서 인터페이스 저장”
UCLASS()
class MYGAME_API AMyController : public APlayerController
{
GENERATED_BODY()
// 에디터에서 인터페이스를 구현한 Actor를 할당 가능
UPROPERTY(EditAnywhere, Category = "Interaction")
TScriptInterface<IInteractableInterface> CurrentInteractable;
void ActivateInteractable()
{
if (CurrentInteractable)
{
IInteractableInterface::Execute_Interact(
CurrentInteractable.GetObject(), this);
}
}
};

// DamageableInterface.h (별도 선언)
UINTERFACE(MinimalAPI, BlueprintType)
class UDamageableInterface : public UInterface { GENERATED_BODY() };
class MYGAME_API IDamageableInterface
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Damage")
void TakeDamage(float Amount, AActor* DamageCauser);
virtual void TakeDamage_Implementation(float Amount, AActor* DamageCauser) {}
virtual bool IsAlive() const = 0;
};
// Enemy.h — 두 인터페이스 동시 구현
UCLASS()
class MYGAME_API AEnemy : public ACharacter,
public IInteractableInterface,
public IDamageableInterface
{
GENERATED_BODY()
public:
// IInteractableInterface
virtual FString GetInteractionPrompt() const override;
virtual void Interact_Implementation(AActor* Interactor) override;
// IDamageableInterface
virtual void TakeDamage_Implementation(float Amount, AActor* DamageCauser) override;
virtual bool IsAlive() const override;
private:
float Health = 100.f;
};

6. 실전 패턴 — 상호작용 시스템

Section titled “6. 실전 패턴 — 상호작용 시스템”
// InteractionComponent.cpp — LineTrace로 상호작용 가능한 오브젝트 탐지
void UInteractionComponent::TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
FHitResult HitResult;
FVector Start = Camera->GetComponentLocation();
FVector End = Start + Camera->GetForwardVector() * InteractionRange;
FCollisionQueryParams Params;
Params.AddIgnoredActor(GetOwner());
if (GetWorld()->LineTraceSingleByChannel(HitResult, Start, End, ECC_Visibility, Params))
{
AActor* HitActor = HitResult.GetActor();
if (HitActor && HitActor->Implements<UInteractableInterface>())
{
// 인터페이스를 구현한 Actor 감지
if (IInteractableInterface::Execute_CanInteract(HitActor, GetOwner()))
{
// UI에 프롬프트 표시
FString Prompt = Cast<IInteractableInterface>(HitActor)->GetInteractionPrompt();
ShowInteractionPrompt(Prompt);
FocusedActor = HitActor;
return;
}
}
}
HideInteractionPrompt();
FocusedActor = nullptr;
}
void UInteractionComponent::TryInteract()
{
if (FocusedActor && FocusedActor->Implements<UInteractableInterface>())
{
IInteractableInterface::Execute_Interact(FocusedActor, GetOwner());
}
}

  • UE 인터페이스는 UMyInterface (리플렉션용) + IMyInterface (함수 선언용) 두 클래스 쌍으로 구성
  • BlueprintNativeEvent 함수는 _Implementation 접미사로 C++ 구현, 호출 시 Execute_ 사용
  • Execute_Func(Target) 방식은 Blueprint·C++ 구현 모두 올바르게 디스패치
  • UPROPERTY에서 인터페이스를 저장할 때 TScriptInterface<IMyInterface> 사용
  • Implements<UMyInterface>() 로 Blueprint 클래스의 인터페이스 구현 여부도 런타임 확인 가능