안선생의 개발 블로그
[UE5] 인터페이스 본문
인터페이스
인터페이스 클래스는 (잠재적으로) 무관한 클래스 세트가 공통의 함수 세트를 구현할 수 있도록 하는 데 쓰입니다. 그대로라면 유사성이 없었을 크고 복잡한 클래스들에 어떤 게임 함수 기능을 공유시키고자 하는 경우 매우 좋습니다. 예를 들어 트리거 볼륨에 들어서면 함정이 발동되거나, 적에게 경보가 울리거나, 플레이어에게 점수를 주는 시스템을 가진 게임이 있다 칩시다. 함정, 적, 점수에서 ReactToTrigger (트리거에 반응) 함수를 구현하면 될 것입니다. 하지만 함정은 AActor 에서 파생될 수도, 적은 특수 APawn 또는 ACharacter 서브클래스일 수도, 점수는 UDataAsset 일 수도 있습니다. 이 모든 클래스에 공유 함수 기능이 필요하지만, UObject 말고는 공통 조상이 없습니다. 이럴 때 인터페이스를 추천합니다.
위에 공식문서를 보면 저렇게 설명되있는데 인터페이스는 간단하게 모든 클래스에서 기능을 공유하는 클래스입니다.
EX) 캐릭터가 데미지를 주는데 데미지 받는 액터가 캐릭터일수도 있고 동물일수도 있고 항아리같은 꺠지는 액터일수도 있다. 각자 서로 다른 클래스이지만 같은 함수를 공유할 떄 사용할 수 있다.
인터페이스 선언
먼저 인터페이스 클래스를 하나 만듭니다. 만든 후
#pragma once
#include "CombatInterface.generated.h"
UINTERFACE(Blueprintable)
class UCombatInterface : public UInterface
{
GENERATED_BODY()
};
class ICombatInterface
{
GENERATED_BODY()
public:
/** 공유 기능 . */
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category="Hit")
void GetHit();
};
public: 아래부터 공유할 메서드를 작성하면 된다. 인터페이스를 가지고있는 클래스마다 GetHit기능을 가지고 있었으면 좋을거 같아서 선언
인터페이스 지정자
인터페이스 | 지정자의미 |
BlueprintType | 이 클래스를 블루프린트에서 변수로 사용할 수 있는 유형으로 노출합니다. |
DependsOn=(ClassName1, ClassName2, ...) | 나열된 모든 클래스는 이 클래스에 앞서 컴파일됩니다. ClassName 은 같은 (또는 기존) 패키지의 클래스를 지정해야 합니다. 쉼표로 구분되는 단일 DependsOn 줄, 또는 각 클래스마다 별도의 DependsOn 줄을 사용하여 다중 종속 클래스를 지정할 수 있습니다. 컴파일러는 이미 컴파일된 클래스에 있는 것만 알기때문에, 다른 클래스에 선언된 구조체 또는 열거형을 사용할 때는 중요합니다. |
MinimalAPI | 클래스의 형 정보만 다른 모듈에서 사용할 수 있도록 익스포트하게 만듭니다. 클래스는 형변환 가능하지만, 그 클래스의 함수는 (인라인 메서드를 제외하고) 호출할 수 없습니다. 그러면 다른 모듈에서 접근할 수 없는 함수가 모두 필요치 않은 클래스에 대해 모든 것을 익스포트하지 않아 컴파일 시간이 빨라집니다. |
인터페이스 구현
새 클래스에서 인터페이스를 사용하려면, 단순히 (사용중인 UObject 기반 클래스에 추가로) 접두사가 "I" 인 인터페이스 클래스를 상속하기만 하면 됩니다.
class ATrap : public AActor, public ICombatInterface
{
GENERATED_BODY()
public:
virtual void GetHit() override;
};
클래스에 상속받고 기능을 구현해주면 됩니다.
주어진 클래스의 인터페이스 구현 여부 확인
인터페이스를 구현하는 두 C++ 와 블루프린트 클래스 사이의 호환을 위해서는, 다음 함수 중 하나를 사용하면 됩니다:
bool bIsImplemented = OriginalObject->GetClass()->ImplementsInterface(UReactToTriggerInterface::StaticClass()); // OriginalObject 가 UReactToTriggerInterface 를 구현한다면 bIsImplemented 는 true 가 됩니다.
IReactToTriggerInterface* ReactingObject = Cast<IReactToTriggerInterface>(OriginalObject); // OriginalObject 가 UReactToTriggerInterface 를 구현한다면 ReactingObject 는 null 이외의 값이 됩니다.
다른 언리얼 유형으로의 형 변환
언리얼 엔진의 형변환 시스템은 한 인터페이스에서 다른 인터페이스로, 또는 인터페이스에서 적합한 경우 언리얼 유형으로 형 변환을 지원합니다.
IReactToTriggerInterface* ReactingObject = Cast<IReactToTriggerInterface>(OriginalObject); // 인터페이스가 구현된 경우 ReactingObject 는 null 이외의 값이 됩니다.
ISomeOtherInterface* DifferentInterface = Cast<ISomeOtherInterface>(ReactingObject); // ReactingObject 가 null 이외의 값이고 ISomeOtherInterface 를 구현하는 경우 DifferentInterface 는 null 이외의 값이 됩니다.
AActor* Actor = Cast<AActor>(ReactingObject); // ReactingObject 가 null 이외의 값이고 OriginalObject 는 AActor 또는 AActor 파생 클래스인 경우, A
if(ReactingObject)
{
ReactingObject->GetHit(); //인터페이스에 있는 함수 사용
}
위와 같은 방법으로 인터페이스를 형변환 후 인터페이스를 사용하시면 됩니다.
블루프린트 구현가능 클래스
블루프린트가 이 인터페이스를 구현할 수 있도록 하려면, Blueprintable 메타데이터 지정자를 사용해야 합니다. 블루프린트 클래스가 덮어쓰려는 모든 인터페이스 함수는 BlueprintNativeEvent 또는 BlueprintImplementableEvent 여야 합니다. BlueprintCallable 마킹된 함수는 여전히 호출은 가능할 것이나, 덮어쓰기는 불가능합니다. 다른 모든 함수는 블루프린트에서 접근할 수 없을 것입니다.
#pragma once
#include "CombatInterface.generated.h"
UINTERFACE(Blueprintable)
class UCombatInterface : public UInterface
{
GENERATED_BODY()
};
class ICombatInterface
{
GENERATED_BODY()
public:
/** 공유 기능 . */
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category="Hit")
void GetHit(); //블루프린트에서 구현해야함
UFUNCTION(BlueprintCallable, BlueprintNativeEvent , Category="Hit")
void GetHit(); //C++ 블루프린트 둘다 구현 가능
};
이와 같이 블루프린트 구현가능 인터페이스를 만들면 상속받는 클래스에서는 Implementation을 붙여줘야함
virtual void GetHit_Implementation() override;
블루프린트 구현가능 인터페이스를 사용할라면 Execute를 이용해서 사용
if (Actor->Implements<UCombatInterface>())
{
ICombatInterface::Execute_GetHit(Actor);
}
https://docs.unrealengine.com/4.27/ko/ProgrammingAndScripting/GameplayArchitecture/Interfaces/
인터페이스
인터페이스 생성 및 구현 관련 레퍼런스입니다.
docs.unrealengine.com
'언리얼 > 언리얼 C++' 카테고리의 다른 글
[UE5] TObjectPtr (0) | 2023.11.18 |
---|---|
[UE5 C++] OnComponentBeginOverlap (0) | 2023.11.16 |
[UE5] C++ 블루프린트 연결하기 (0) | 2023.11.02 |
[UE5] 언리얼 라이브 코딩 (0) | 2023.10.31 |
[UE5] 생성자, BeginPlay,Tick 알아보기 (1) | 2023.10.28 |