[UE5] 블루프린트 클래스 로드 및 스폰: StaticLoadClass와 LoadObject

ChangJin·2024년 11월 4일
0

Unreal Engine5

목록 보기
107/114
post-thumbnail

개요

이 글에서는 Unreal Engine에서 블루프린트 클래스 로드와 스폰을 다루며, 이를 위한 함수인 StaticLoadClass, LoadObject의 차이점과 사용법을 살펴보겠습니다.


1. 블루프린트 클래스 로드 및 스폰하기: StaticLoadClassLoadObject의 기본 사용법

Unreal Engine에서 블루프린트를 로드해 클래스를 스폰할 때 StaticLoadClassLoadObject를 주로 사용하게 됩니다. 이들 함수는 콘텐츠 브라우저의 경로를 통해 블루프린트를 코드에서 참조 가능하도록 만들어주며, 필요한 타입의 객체나 클래스로 변환할 수 있도록 지원합니다.

블루프린트 클래스 경로는 다음 형식이어야 합니다. 경로 끝에 _C 접미사가 반드시 포함되어야 합니다.

  • 경로 형식 예시: "/Game/Blueprints/MyBlueprint.MyBlueprint_C"
FString ClassPath = "/Game/Blueprints/MyBlueprint.MyBlueprint_C";
UClass* LoadedClass = StaticLoadClass(AActor::StaticClass(), nullptr, *ClassPath);

if (LoadedClass)
{
    UE_LOG(LogTemp, Log, TEXT("블루프린트 클래스 로드 성공: %s"), *LoadedClass->GetName());
}
else
{
    UE_LOG(LogTemp, Error, TEXT("블루프린트 클래스 로드 실패: 경로를 확인하세요."));
}

2. TSubclassOf에 로드한 클래스 저장하기

블루프린트를 경로를 통해 TSubclassOf 타입으로 로드하면, 여러 번 사용할 수 있으며 SpawnActor로 쉽게 스폰할 수 있습니다. TSubclassOf는 특정 클래스의 하위 클래스를 참조하도록 설계되어 있어, 캐스팅이 용이하고 오류 가능성이 적습니다.

TSubclassOf<AActor> ItemClass;

// 경로에서 클래스 로드 후 TSubclassOf에 저장
FString BlueprintPath = "/Game/Blueprints/MyWeaponBlueprint.MyWeaponBlueprint_C";
UClass* LoadedClass = StaticLoadClass(AActor::StaticClass(), nullptr, *BlueprintPath);

if (LoadedClass && LoadedClass->IsChildOf(AActor::StaticClass()))
{
    ItemClass = LoadedClass;
    UE_LOG(LogTemp, Log, TEXT("클래스가 TSubclassOf에 저장되었습니다."));
}
else
{
    UE_LOG(LogTemp, Error, TEXT("클래스 로드 실패 또는 AActor의 하위 클래스가 아닙니다."));
}

// 저장된 클래스를 통해 스폰
if (ItemClass)
{
    AActor* SpawnedActor = GetWorld()->SpawnActor<AActor>(ItemClass);
    if (SpawnedActor)
    {
        UE_LOG(LogTemp, Log, TEXT("스폰 성공: %s"), *SpawnedActor->GetName());
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("스폰 실패: ItemClass가 올바르지 않습니다."));
    }
}

이렇게 하면 TSubclassOf 타입의 ItemClass를 이용해 손쉽게 객체를 스폰할 수 있습니다.


3. 주요 Load 함수들: StaticLoadClass vs LoadObject vs StaticLoadObject

Unreal Engine에서 리소스를 로드할 때 사용하는 StaticLoadClass, LoadObject, StaticLoadObject는 각기 다른 목적과 특징을 가지고 있습니다. 이 함수들의 차이와 사용 예제를 비교하여 언제 어떤 함수를 사용해야 하는지에 대해 정리해봤습니다.

3.1 StaticLoadClass

StaticLoadClassUClass를 로드하는 함수로, 블루프린트 클래스를 로드할 때 주로 사용됩니다. StaticLoadClass는 클래스의 타입을 기반으로만 작동하기 때문에 객체 인스턴스를 생성하는 것은 불가능하며, 클래스 자체만을 가져옵니다.

FString ClassPath = "/Game/Blueprints/test.test_C";
UClass* LoadedClass = StaticLoadClass(AActor::StaticClass(), nullptr, *ClassPath);

특징

  • 대상: UClass (클래스 정보 자체)
  • 주용도: 블루프린트 클래스 로드 및 스폰 목적
  • 사용 예: 클래스를 로드해 SpawnActor 등으로 객체를 생성할 준비를 할 때

3.2 LoadObject

LoadObject는 특정 객체를 로드할 때 사용하는 함수로, StaticLoadClass와 달리 UObject 타입의 인스턴스를 직접 로드할 수 있습니다. 경로에서 텍스처, 사운드, 메시와 같은 실제 리소스를 로드하여 사용할 때 씁니다.

FString TexturePath = "/Game/Textures/testTexture";
UTexture2D* Texture = LoadObject<UTexture2D>(nullptr, *TexturePath);

if (Texture)
{
    UE_LOG(LogTemp, Log, TEXT("텍스처 로드 성공"));
}
else
{
    UE_LOG(LogTemp, Error, TEXT("텍스처 로드 실패"));
}

특징

  • 대상: UObject 타입의 인스턴스 (예: UTexture2D, USoundBase 등)
  • 주용도: 리소스(텍스처, 사운드 등) 로드
  • 사용 예: 특정 경로의 텍스처, 사운드 등을 동적으로 로드하여 UI나 오브젝트에 할당할 때

3.3 StaticLoadObject

StaticLoadObjectLoadObject와 비슷한 기능을 하지만, 내부에서 객체 타입에 대한 고정된 클래스 정보가 필요할 때 주로 사용합니다. 따라서 LoadObject가 주로 사용되지만, StaticLoadObject는 리소스를 명시적으로 고정하여 로드할 때 더 선호됩니다.

FString MeshPath = "/Game/Meshes/testMesh";
UStaticMesh* Mesh = Cast<UStaticMesh>(StaticLoadObject(UStaticMesh::StaticClass(), nullptr, *MeshPath));

if (Mesh)
{
    UE_LOG(LogTemp, Log, TEXT("메시 로드 성공"));
}
else
{
    UE_LOG(LogTemp, Error, TEXT("메시 로드 실패"));
}

특징

  • 대상: UObject 타입의 인스턴스 (다만 LoadObject와의 명확한 차이 없음)
  • 주용도: 명시적 클래스 타입을 고정하여 특정 리소스를 로드
  • 사용 예: 특정 리소스를 캐스팅 없이 명확히 고정하여 로드할 때

요약: 어떤 함수를 언제 사용할까?

함수대상주용도사용 예
StaticLoadClassUClass클래스 로드블루프린트 클래스 로드 및 스폰 준비
LoadObjectUObject객체 인스턴스 로드텍스처, 사운드, 메시 등 리소스 로드
StaticLoadObjectUObject객체 인스턴스 로드 (타입 고정)특정 타입으로 명확히 리소스를 로드

이 표를 참고하여 프로젝트의 요구 사항에 맞는 Load 함수를 선택하면, 효율적이고 최적화된 코드 작성이 가능합니다.


그런데, 만약 반대로 사용하게 된다면 어떤 일이 일어날까?

Unreal Engine에서 StaticLoadClassLoadObject는 특정 목적에 맞게 설계된 함수들이기 때문에, 올바르지 않은 용도로 사용하게 되면 오류가 발생할 수 있습니다.

1. StaticLoadClass를 사용해 텍스처, 사운드, 메시 등 리소스를 로드할 경우

StaticLoadClassUClass 타입의 데이터를 로드하기 위한 함수이므로, 텍스처, 사운드, 메시 등 리소스를 로드하려고 하면 실패하거나 타입 불일치 오류가 발생합니다. StaticLoadClass는 객체 인스턴스가 아닌 클래스 정보만 로드하기 때문에, 이를 통해 직접적인 리소스(예: UTexture2DUSoundBase 등) 접근은 불가능합니다.

예시 코드에서 잘못된 사용 예를 보면:

// 잘못된 사용: 텍스처 로드에 StaticLoadClass 사용
FString TexturePath = "/Game/Textures/MyTexture";
UTexture2D* Texture = Cast<UTexture2D>(StaticLoadClass(UTexture2D::StaticClass(), nullptr, *TexturePath));

위 코드는 다음과 같은 오류를 발생시킬 수 있습니다.

  • Texture는 항상 nullptr이 반환됩니다.
  • Log에서 "Cannot find class""Failed to load class"와 같은 오류 메시지가 출력됩니다.
  • Unreal Engine은 런타임에서 오류를 로그에 기록하며, 올바르지 않은 타입에 대해 로드를 거부합니다.

따라서 텍스처와 같은 리소스를 로드할 때는 반드시 LoadObject<UTexture2D>(nullptr, *TexturePath)와 같은 적절한 함수를 사용해야 합니다.


2. LoadObject를 사용해 블루프린트 클래스 로드 및 스폰 준비를 할 경우

반대로, LoadObjectUObject 인스턴스를 직접 로드하는 데 사용되므로, LoadObject<UClass>(nullptr, *ClassPath) 형태로 블루프린트 클래스를 로드하려 하면 실제 객체 인스턴스가 아닌 클래스 정보만 필요한 경우에 불필요한 인스턴스를 생성하려고 시도할 수 있습니다.

예를 들어, 블루프린트 클래스를 로드하는데 LoadObject를 사용하면 런타임에서 다음과 같은 문제가 발생할 수 있습니다.

// 잘못된 사용: 블루프린트 클래스 로드에 LoadObject 사용
FString BlueprintPath = "/Game/Blueprints/MyBlueprint.MyBlueprint_C";
UClass* MyClass = LoadObject<UClass>(nullptr, *BlueprintPath);

귀찮지만 UBluePrintGeneratedClass로 다음처럼 사용해야합니다.

FString BlueprintPath = "/Game/Blueprints/MyBlueprint.MyBlueprint_C";
UBluePrintGeneratedClass* LoadedBP = LoadObject<UClass>(nullptr, *BlueprintPath);
if(LoadedBP)
{
	testBlueprintClass* _blueprintclass = Cast<testBlueprintClass>(LoadedBP);
}

문제점:

  • LoadObject는 인스턴스를 생성하려고 시도하지만, UClass는 인스턴스화할 수 없는 타입이므로 불필요한 리소스 사용으로 이어질 수 있습니다.
  • MyClass는 항상 nullptr일 가능성이 높으며, 이로 인해 런타임에서 오류 로그가 생성될 수 있습니다.
  • Unreal Engine은 런타임에서 로드 오류를 발생시키며, UClassLoadObject로 직접 로드할 수 없다는 점을 알립니다.

올바른 사용

  • StaticLoadClass: 클래스 정보(즉, UClass)만 로드하며, 인스턴스화되지 않습니다. 블루프린트 클래스를 로드하여 스폰 준비를 할 때 적합합니다.
  • LoadObject: 특정 객체 인스턴스(예: 텍스처, 사운드, 메시 등)를 로드할 때 사용하며, 클래스 자체보다는 개별 리소스 사용 시 유용합니다.

잘못사용할 경우 오류 로그가 생성되거나, NULL 참조로 인한 크래시와 같은 문제가 발생할 수 있습니다.

결론

Unreal Engine에서 블루프린트 클래스를 로드하고 활용하는 방법은 게임 개발에서 매우 중요합니다. StaticLoadClass를 이용해 TSubclassOf로 클래스를 관리하고, 다양한 Load 함수들의 차이를 이해하고 적절히 활용함으로써 큰 오류를 미리 방지할 수 있습니다.

다음에는 UBluePrintGeneratedClass, UClass, UObject에 대해서 더 자세하게 알아볼 예정입니다.

profile
게임 프로그래머

0개의 댓글