[Unreal Engine 5] TSubclassOf<T>

2026. 1. 16. 20:47·프로그래밍/Unreal Engine 5

TSubclassOf<T>는 언리얼 엔진 C++ 프로그래밍, 특히 콘텐츠와 코드의 분리(Data-Driven Design)를 구현할 때 가장 빈번하게 사용되는 핵심 템플릿 클래스이다.

간단히 말해, "특정 클래스(또는 그 자식 클래스)의 원본(Type/Class Information)을 담는 안전한 변수"라고 정의할 수 있다.


1. TSubclassOf란 무엇인가?

C++의 UClass*는 모든 언리얼 오브젝트의 메타데이터(클래스 정보)를 담을 수 있는 포인터이다. 하지만 UClass*는 너무 범위가 넓다. AActor가 필요한 자리에 UTexture의 클래스 정보가 들어와도 컴파일러는 막지 못한다. TSubclassOf<T>는 이 문제를 해결할 수 있다.

  • 타입 안정성 (Type Safety): 템플릿 인자 T로 지정된 클래스나, 그 T를 상속받은 자식 클래스만 할당할 수 있다.
  • 에디터 편의성: 에디터의 '디테일 패널(Details Panel)'에서 드롭다운 메뉴를 열었을 때, 관련 없는 클래스는 필터링하고 호환되는 클래스만 보여준다.

2. 기본 사용법 및 시나리오

가장 흔한 사용 사례는 "C++에서 스폰(Spawn)할 액터의 종류를 블루프린트에서 지정하고 싶을 때"이다.

시나리오: 무기 스폰 시스템

C++ 코드는 무기를 스폰하는 로직(SpawnActor)만 작성하고, 실제로 스폰될 무기가 '라이플'인지 '로켓 런처'인지는 에디터에서 설정.

헤더 파일 (.h)

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyCharacter.generated.h"

// 전방 선언 (컴파일 시간 단축)
class AMyWeapon; 

UCLASS()
class MYGAME_API AMyCharacter : public ACharacter
{
    GENERATED_BODY()

public:
    // 에디터에서 할당할 무기 클래스 변수
    // AMyWeapon을 상속받은 블루프린트 클래스만 선택 가능.
    UPROPERTY(EditDefaultsOnly, Category = "Combat")
    TSubclassOf<AMyWeapon> WeaponClass;

    // 실제 스폰된 무기 인스턴스를 가리키는 포인터 (UE5: TObjectPtr 권장)
    UPROPERTY(Transient)
    TObjectPtr<AMyWeapon> CurrentWeapon;

    virtual void BeginPlay() override;
};

소스 파일 (.cpp)

#include "MyCharacter.h"
#include "MyWeapon.h"

void AMyCharacter::BeginPlay()
{
    Super::BeginPlay();

    // 1. 유효성 검사 (매우 중요)
    // 에디터에서 WeaponClass를 비워뒀을 경우 크래시 방지
    if (WeaponClass) 
    {
        // 2. 스폰 파라미터 설정
        FActorSpawnParameters SpawnParams;
        SpawnParams.Owner = this;
        SpawnParams.Instigator = GetInstigator();

        // 3. 월드에 액터 스폰
        // GetWorld()->SpawnActor<T>(...)를 사용하면 캐스팅 없이 바로 T* 타입을 반환받는다.
        CurrentWeapon = GetWorld()->SpawnActor<AMyWeapon>(WeaponClass, GetActorTransform(), SpawnParams);

        if (CurrentWeapon)
        {
            // 무기 장착 로직 등...
            UE_LOG(LogTemp, Log, TEXT("Weapon Spawned Successfully: %s"), *CurrentWeapon->GetName());
        }
    }
    else
    {
        UE_LOG(LogTemp, Warning, TEXT("WeaponClass is not set in %s"), *GetName());
    }
}

3. UE5 최적화 및 주의사항 (Critical)

오픈 월드나 규모가 큰 게임에서는 TSubclassOf 사용 시 메모리 관리에 주의해야 한다.

A. 하드 레퍼런스 (Hard Reference) 문제

UPROPERTY로 선언된 TSubclassOf<AActor> MyActorClass에 특정 블루프린트(예: BP_HeavyTank)를 할당하면, 이 캐릭터가 로드될 때 BP_HeavyTank도 메모리에 강제로 함께 로드된다.

만약 BP_HeavyTank가 거대한 텍스처와 사운드를 참조하고 있다면, 단순히 클래스 정보만 필요했을 뿐인데 수백 MB의 메모리가 낭비될 수 있다.

B. 해결책: TSoftClassPtr (소프트 레퍼런스)

즉시 스폰해야 하는 경우가 아니라면, 혹은 에셋 사이즈가 크다면 TSoftClassPtr를 사용하여 필요할 때 비동기 로딩(Async Load)하는 것이 UE5의 표준 최적화 방식이다.

// 헤더: 소프트 레퍼런스로 선언 (메모리에 즉시 로드되지 않음)
UPROPERTY(EditDefaultsOnly, Category = "Combat")
TSoftClassPtr<AMyWeapon> SoftWeaponClass;

// 구현: 필요할 때 로드 (동기 로드 예시, 실제론 AssetManager를 통한 비동기 권장)
void AMyCharacter::EquipWeapon()
{
    if (SoftWeaponClass.IsPending())
    {
        // 에셋을 동기적으로 로드 (프레임 드랍 발생 가능, 비동기 로딩 권장)
        SoftWeaponClass.LoadSynchronous(); 
    }

    TSubclassOf<AMyWeapon> LoadedClass = SoftWeaponClass.Get();
    if (LoadedClass)
    {
        GetWorld()->SpawnActor<AMyWeapon>(LoadedClass, ...);
    }
}

4. TSubclassOf vs UClass* 비교

5. 자주 발생하는 실수 및 팁

  1. 인스턴스가 아님:
    • 자주 하는 실수는 WeaponClass->Fire() 처럼 호출하려 하는 것이다. WeaponClass는 설계도(Class)이지 실제 만들어진 물체(Instance)가 아니다. 반드시 SpawnActor를 통해 인스턴스화해야 한다.
  1. 블루프린트 전용 클래스:
    • C++ 클래스 없이 블루프린트로만 만든 클래스(Blueprint Type)도 TSubclassOf<AActor>나 TSubclassOf<UUserWidget> 등에 할당할 수 있다. 이것이 C++와 블루프린트 하이브리드 개발의 핵심.
  1. 순환 의존성 (Circular Dependency):
    • 헤더 파일에서 TSubclassOf를 쓸 때, 해당 클래스의 헤더를 #include 하지 말고 class AMyWeapon; 처럼 전방 선언(Forward Declaration)을 사용해야 한다. 컴파일 시간을 줄이고 의존성 꼬임을 방지.

 

'프로그래밍 > Unreal Engine 5' 카테고리의 다른 글

[Unreal Engine 5] GAS(Gameplay Ability System)  (0) 2026.01.26
[Unreal Engine 5] 충돌처리를 위해 바인딩(Binding)을 하는 이유  (0) 2026.01.23
[Unreal Engine 5] UPROPERTY()와 지정자(Specifier)들  (0) 2026.01.15
[Unreal Engine 5] 액터의 라이프 사이클  (2) 2026.01.09
[Unreal Engine 5] 언리얼 엔진 5의 스마트 포인터  (1) 2026.01.08
'프로그래밍/Unreal Engine 5' 카테고리의 다른 글
  • [Unreal Engine 5] GAS(Gameplay Ability System)
  • [Unreal Engine 5] 충돌처리를 위해 바인딩(Binding)을 하는 이유
  • [Unreal Engine 5] UPROPERTY()와 지정자(Specifier)들
  • [Unreal Engine 5] 액터의 라이프 사이클
hanong8
hanong8
hanong8 님의 블로그 입니다.
  • hanong8
    HaNong
    hanong8
  • 전체
    오늘
    어제
    • 분류 전체보기 (102) N
      • 프로그래밍 (99) N
        • Unreal Engine 5 (45)
        • C++ (22)
        • UML (2)
        • 자료구조 (2)
        • 알고리즘 (9)
        • 개발일지 (4)
        • DirectX11 (5)
        • Git (2)
        • 코드카타 (8) N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
hanong8
[Unreal Engine 5] TSubclassOf<T>
상단으로

티스토리툴바