본문 바로가기
개발이야기/언리얼 c++

언리얼 C++: TScriptInterface

by oddsilk 2024. 5. 28.

TScriptInterface란?

TScriptInterface는 Unreal Engine에서 인터페이스 기반 프로그래밍을 지원하기 위해 사용되는 템플릿 클래스입니다.

이 클래스는 UObject 기반 클래스에서 인터페이스를 구현하고 해당 인터페이스를 참조할 수 있는 기능을 제공합니다.

 

이를 통해 객체 지향 프로그래밍의 다형성 기능을 활용하고, 블루프린트와 C++ 코드 간의 상호 운용성을 높일 수 있습니다. TScriptInterface를 사용하여 인터페이스를 안전하게 참조하고 호출할 수 있으며, 이는 코드의 유연성과 재사용성을 크게 향상시킵니다.

 

< 언리얼 엔진 공식문서 >

 

 

https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/CoreUObject/UObject/TScriptInterface?application_version=5.3

 

 

1.주요 기능 및 개념

  1. 인터페이스 참조: TScriptInterface는 특정 인터페이스를 구현하는 UObject를 참조할 수 있습니다. 이는 인터페이스를 통해 객체의 기능을 추상화하고 다형성을 제공하는 데 유용합니다.
  2. 안전한 캐스팅: TScriptInterface는 내부적으로 두 개의 포인터를 유지합니다. 하나는 객체를 가리키고, 다른 하나는 인터페이스를 가리킵니다. 이를 통해 인터페이스를 안전하게 캐스팅하고 호출할 수 있습니다.
  3. 블루프린트 지원: TScriptInterface는 블루프린트에서 인터페이스를 사용할 수 있도록 지원합니다. 블루프린트에서 인터페이스를 사용할 때, TScriptInterface를 사용하여 인터페이스를 참조할 수 있습니다.
// MyGameInstance.h
#pragma once

#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "MyInterface.h"
#include "MyGameInstance.generated.h"

UCLASS()
class MYPROJECT_API UMyGameInstance : public UGameInstance
{
    GENERATED_BODY()

public:
    virtual void Init() override;

private:
    TScriptInterface<IMyInterface> MyInterfaceInstance;
};

// MyGameInstance.cpp
#include "MyGameInstance.h"
#include "MyActor.h"

void UMyGameInstance::Init()
{
    Super::Init();

    // AMyActor를 생성하고 인터페이스를 설정합니다.
    AMyActor* MyActor = GetWorld()->SpawnActor<AMyActor>();

    // TScriptInterface에 인터페이스를 구현한 객체를 설정합니다.
    MyInterfaceInstance.SetObject(MyActor); // 참조할 객체를 설정합니다
    MyInterfaceInstance.SetInterface(Cast<IMyInterface>(MyActor)); // TscriptInterface가 참조할 인터페이스를 설정합니다

    // 인터페이스를 통해 함수 호출
    if (MyInterfaceInstance)
    {
        MyInterfaceInstance->MyFunction();
    }
}

 

 

2. 주의할 점

TScriptInterface는 단순히 인터페이스와 해당 인터페이스를 구현하는 객체를 참조할 수 있는 포인터일 뿐, 객체의 수명을 보장하지 않습니다. 따라서 객체가 다른 곳에서 참조되지 않거나 루트에 추가되지 않은 경우, 가비지 수집기에 의해 수집될 수 있습니다.

실제로 이부분을 몰랐다가... 가비지 컬렉터에 수집되어서 한참을 고생한 경험이 있습니다... ㅠ
나중에 소멸자에 로그 찍어보고 수집되는걸 깨닫게 되었다는 비하인드 ;;;

 

 

1. 참조 카운팅 문제

객체의 참조가 유지되지 않아서 가비지 수집기에 의해 수집될 수 있습니다. TScriptInterface는 단순히 객체를 참조할 뿐, 참조 카운트를 증가시키지 않습니다. 따라서 객체의 참조가 유지되지 않으면 가비지 수집기에 의해 수집될 수 있습니다.

2. 객체의 루트 추가

객체를 루트에 추가하여 가비지 수집기의 수집 대상에서 제외할 수 있습니다. 이를 위해 AddToRoot와 RemoveFromRoot를 사용할 수 있습니다.