TSubclassOf<>

특정 클래스의 하위 클래스(서브 클래스)만 참조 할 수 있도록 만들어주는 언리얼 엔진의 템플릿 클래스다.

일반적인 UClass* 포인터가 “어떤 클래스든 가리킬 수 있는 만능 포인터”라면, TSubclassOf<TBaseClass>는 “오직 TBaseClass를 상속받은 녀석들만 가리킬 수 있는 제한된 포인터” 이다.

왜 이런 제한이 필요하냐면, 타입 안정성에 큰 이점을 가진다.

TSubclassOf<>의 필요성 (타입 안정성 확보)

코드를 작성할 때 가장 피하고 싶은 것 중 하나가 런타임 에러다.

특히 언리얼처럼 거대한 프레임워크에서는 작은 실수 하나가 전체 프로젝트에 영향을 미칠 수도 있다.

UClass*를 사용하면 다음과 같은 문제가 발생할 수 있다.

// Bad Example: UClass* 사용 시
UPROPERTY(EditDefaultsOnly, Category=Gameplay)
UClass* MyActorClass; // 여기에 어떤 클래스든 할당 가능.

만약 MyActorClassAPawn 타입의 액터를 넣어야 하는데, 실수로 UTexture2D 같은 전혀 다른 클래스를 할당했다고 가정해 보면, 컴파일은 되겠지만, 나중에 이 MyActorClass를 가지고 GetWorld()->SpawnActor(...)를 호출하는 순간, 게임에 문제가 발생할 수 있다.

// Good Example: TSubclassOf<> 사용 시
UPROPERTY(EditDefaultsOnly, Category=Gameplay)
TSubclassOf<APawn> MyPawnClass; // 오직 APawn의 서브클래스만 할당 가능.

이렇게 선언하는 순간, 컴파일러가 강력한 가드 역할을 해준다.

MyPawnClassAPawn이나 그 하위 클래스(예: AMyPlayerCharacter, AEnemyAI)가 아닌 다른 타입의 클래스를 할당하려고 하면, 컴파일 단계에서 바로 에러를 발생시킨다.

덕분에 런타임에 발생할 수 있는 잠재적인 버그를 미리 차단할 수 있다.

에디터와의 연동 (UPROPERTY)

TSubclassOf<>의 진정한 가치는 UPROPERTY 매크로와 함께 사용할 때 발휘된다.

개발하다 보면 디자이너나 아티스트가 특정 클래스를 직접 선택해야 할 상황이 많다.

예를 들어, “이 발사체는 어떤 종류의 데미지를 줄 것인가?”와 같은 설정이 있겠다.

// UPROPERTY와 TSubclassOf<>의 시너지 효과
UPROPERTY(EditDefaultsOnly, Category=Damage)
TSubclassOf<UDamageType> DamageTypeClass;

이렇게 코드를 작성하고 언리얼 에디터를 열어보면, DamageTypeClass 프로퍼티의 드롭다운 목록에는 오직 UDamageType을 상속받는 클래스들만 나타난다.

UDamageType_Fire, UDamageType_Ice, UDamageType_Poison 등, 우리가 정의해둔 정확한 데미지 타입 클래스들만 보이게 제한을 걸 수 있는 것이다.

디자이너/아티스트를 위한 이점

  • 실수 방지: 불필요한 클래스가 목록에 표시되지 않으니, 실수로 엉뚱한 클래스를 선택할 위험이 줄어든다.
  • 작업 효율 증대: 수많은 클래스 중에서 일일이 찾아 헤맬 필요 없이, 필요한 클래스만 필터링되어 보이므로 작업 속도가 향상된다.
  • 명확한 의도: “이 필드에는 UDamageType만 들어갈 수 있어.”라는 개발자의 의도가 에디터에도 명확하게 전달된다.

TSubclassOf<>의 활용 예시

TSubclassOf<>는 특정 클래스의 인스턴스가 아니라, 클래스 자체의 타입 정보를 다룰 때 사용된다.

주로 다음과 같은 상황에서 유용하게 활용.

  • 액터/오브젝트 스폰 시:
    • GetWorld()->SpawnActor<AMyActor>(MyActorClass, ...);와 같이 특정 타입의 액터를 런타임에 생성할 때, 어떤 클래스를 스폰할지 참조할 때 사용.
  • 기본 속성 (CDO) 접근:
    • 특정 클래스의 Class Default Object (CDO)에 접근하여, 해당 클래스의 기본 설정값을 읽어올 때 유용.
  • 팩토리 패턴 구현 시:
    • 다양한 종류의 아이템이나 오브젝트를 생성하는 팩토리 클래스를 만들 때, 어떤 아이템을 생성할지 클래스 타입을 저장하는 용도로 활용.

댓글남기기