1. 개요
언리얼에서는 TSoftObjectPtr 클래스를 제공한다.
TObjectPtr을 사용하는 것은 많이 보았으나 TSoftObjectPtr은 자주 못 봤던 것 같다.
이번에 이를 어떻게 사용하면 좋을지를 한 번 살펴보고자 한다.
2. 하드 레퍼런싱.
TObjectPtr은 하드 레퍼런스이다.
UE5부터 포인터 타입이 도입되었으며 원시 포인터 대신 사용을 권장하고 있다. (링크)
하드 레퍼런스는 무엇일까?
class _API AWeaponBase : public AItemBase
{
...
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Weapon")
TObjectPtr<USkeletalMeshComponent> SkeletalMeshComponent;
}
AWeaponBase 클래스가 TObjectPtr을 멤버 변수로 가지고 있다면
AWeaponBase 액터가 생성되었을 때 TObjectPtr 객체도 생성되어 메모리에 로드되는 것을 말한다.
즉, 동시에 메모리에 로드되는 것을 말한다.
간단히 생각해보면 이는 당연하다고 생각된다.
무기를 사용하기 위해 생성하였고
무기 멤버 변수 또한 메모리에 생성되어야 데이터에 접근할 수 있기에 문제가 없어 보인다.
하지만
멤버 변수가 2~3개가 아닌 100개 또는 200개라면?
만약 그렇다면 무기를 생성할 때 100개의 객체 또한 한 번에 생성되려고 할 것이다.
이는 많은 메모리 소모와 생성 지연을 야기한다.
이럴 때 필요한 것이 소프트 레퍼런싱이다.
3. 소프트 레퍼런싱
앞에서 하드 레퍼런싱이 많은 메모리 소모가 발생할 수 있다고 얘기를 하였다.
무기 액터가 생성되었을 때
100~200개의 멤버 변수들이 그 즉시 사용되는 상황이라면 (메모리를 참조해야한다면)
하드 레퍼런싱으로 구현을 해야한다.
그러나 바로 사용되지 않으나
플레이어의 트리거 작동이나 일부 조건을 충족하였을 때 사용되는 변수라면
이는 소프트 레퍼런싱으로 구현하는 것이 메모리 최적화에 도움된다.
소프트 레퍼런싱은
무기 액터 생성과 동시에 메모리에 로드되지 않으며 애셋의 주소 문자열을 저장한다.
그리고 개발자가 원하는 타이밍에 주소를 참고하여 애셋을 메모리에 로드할 수 있게 된다.
class _API AWeaponBase : public AItemBase
{
...
// 소프트 레퍼런싱 선언
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Weapon")
TSoftObjectPtr<USkeletalMeshComponent> SkeletalMeshComponent
}
AWeaponBase::AWeaponBase()
{
// 1. 메모리에 로드되지 않음을 확인 (대기 상태 확인)
if (SkeletalMeshComponen.IsPending())
{
// 2. 애셋 메모리 로딩 (동기)
SkeletalMeshComponent.LoadSynchronous();
}
// 3. Get() 함수를 사용하여 메모리 주소 반환
USkeletalMeshComponent* Component = SkeletalMeshComponent.Get();
}
소프트 레퍼런싱은
런타임에서 작동하여 애셋 파일을 읽어들이고 메로리에 로드하는
애셋 로딩 시간이 소요된다.
이러한 지연 시간이 발생하게 되면 게임이 일시적으로 끊겨 보이게 될 수 있다.
이를 해결하기 위해 언리얼에서는 비동기 방식도 제공해준다.
아래 코드는 Lyra 프로젝트에서 비동기 애셋 로딩을 어떻게 구현하였는지 일부 코드를 가져와 보았다. (링크)
void FAsyncMixin::FLoadingState::AsyncLoad(FSoftObjectPath SoftObjectPath, const FSimpleDelegate& DelegateToCall)
{
UE_LOG(LogAsyncMixin, Verbose, TEXT("[0x%X] AsyncLoad '%s'"), this, *SoftObjectPath.ToString());
AsyncSteps.Add(
MakeUnique<FAsyncStep>(
DelegateToCall,
UAssetManager::GetStreamableManager().RequestAsyncLoad(SoftObjectPath, FStreamableDelegate(), FStreamableManager::AsyncLoadHighPriority, false, false, TEXT("AsyncMixin"))
)
);
TryScheduleStart();
}
살펴보면 UAssetManger::GetStreamableManager()를 활용하여 비동기 로딩 구현을 한 것을 살펴볼 수 있다.
향후 비동기 로딩을 필요하게 된다면 아래 사이트를 참조해 구현하면 좋을 듯 하다.
Assets Streaming
Overview In the Unreal Engine, when a UObject references other Assets, they are loaded in memory by default. For example, when a UPROPERTY property is defined in a UObject, the reference is loaded in memory when the owner itself is being loaded. UPROPERTY(
jdelezenne.github.io
'Unrael > Basic' 카테고리의 다른 글
| [Game] 게임 재미 이론 (0) | 2025.03.21 |
|---|---|
| [UE/Basic] 게임 저장 및 로딩 (0) | 2025.03.19 |
| [UE/Basic] FHitResult (0) | 2025.02.26 |
| [UE/Basic] 게임 콘텐츠 구조 (0) | 2025.02.10 |
| [UE/Basic] 데이터 테이블 (0) | 2025.02.07 |