PART 4 · 강의 1/4

Asset 참조 관리

Hard vs Soft Reference로 메모리 풋프린트를 최적화합니다

01

Hard Reference

직접 참조의 문제점

Hard Reference는 오브젝트 A가 오브젝트 B를 직접 참조하여 A가 로드될 때 B도 자동으로 함께 로드됩니다.

문제점

연쇄 효과로 불필요한 에셋까지 메모리에 로드됩니다. 주의하지 않으면 게임 시작 시 100% 에셋 로드 상황이 발생할 수 있습니다!

🔗 Hard vs Soft Reference
Hard Reference ❌

A 로드 → B 자동 로드
연쇄 효과로 메모리 급증
제어 불가

Soft Reference ✅

경로 문자열로 참조
로드 시점 직접 제어
메모리 최적화

❌ Hard Reference 예시 (위험!)
코드 보기
// Hard Reference - 위험! UPROPERTY(EditAnywhere) UStaticMesh* MeshAsset; // 이 클래스 로드 시 메시도 로드 UPROPERTY(EditAnywhere) TSubclassOf<AActor> ActorClass; // 클래스도 Hard Reference

Hard Reference 발생 원인

원인 해결책
직접 UProperty 참조 TSoftObjectPtr 사용
블루프린트 캐스팅 인터페이스 사용
직접 클래스 참조 TSoftClassPtr 사용
02

Soft Reference

간접 참조로 메모리 제어

Soft Reference는 오브젝트 A가 오브젝트 B를 경로 문자열로 간접 참조합니다. 에셋이 자동으로 로드되지 않아 로드 시점을 직접 제어할 수 있습니다.

⭐ Soft Reference 사용법
코드 숨기기
// Soft Object Pointer UPROPERTY(EditAnywhere) TSoftObjectPtr<UStaticMesh> MeshAsset; // Soft Class Pointer UPROPERTY(EditAnywhere) TSoftClassPtr<AActor> ActorClass; // 로드 확인 if (MeshAsset.IsValid()) { UStaticMesh* Mesh = MeshAsset.Get(); } // 동기 로드 (블로킹) UStaticMesh* Mesh = MeshAsset.LoadSynchronous();
비동기 로드 (권장)
코드 보기
// FStreamableManager를 통한 비동기 로드 FStreamableManager& StreamableManager = UAssetManager::GetStreamableManager(); StreamableManager.RequestAsyncLoad( MeshAsset.ToSoftObjectPath(), FStreamableDelegate::CreateUObject( this, &AMyActor::OnMeshLoaded ) ); void AMyActor::OnMeshLoaded() { if (MeshAsset.IsValid()) { MeshComponent->SetStaticMesh(MeshAsset.Get()); } }
03

참조 분석 도구

의존성 확인 및 디버깅

🔍 참조 분석 도구

📊 Reference Viewer

그래프로 참조 관계 시각화
Asset > Reference Viewer

📦 Size Map

트리맵으로 에셋 크기 비교
Window > Developer Tools > Size Map

디버깅 팁

예상보다 큰 에셋이 있다면 Reference Viewer로 숨겨진 의존성을 확인하세요. 종종 불필요한 Hard Reference가 메모리 폭발의 원인입니다.

04

Asset Manager와 Primary Asset

체계적인 에셋 관리 시스템

UAssetManager는 Primary Asset을 체계적으로 관리하는 싱글톤 시스템입니다. 에셋을 타입별로 분류하고, 비동기 로드/언로드를 중앙에서 제어할 수 있습니다.

// 커스텀 Asset Manager 클래스 UCLASS() class UMyAssetManager : public UAssetManager { GENERATED_BODY() public: static UMyAssetManager& Get(); // Primary Asset 비동기 로드 void LoadItemAsset(const FPrimaryAssetId& AssetId, FStreamableDelegate OnLoaded); // 번들로 관련 에셋 일괄 로드 void LoadAssetBundle(const FPrimaryAssetId& AssetId, const TArray<FName>& Bundles); }; // 사용 예시 FPrimaryAssetId WeaponId(FPrimaryAssetType("Weapon"), FName("Sword_01")); UMyAssetManager::Get().LoadItemAsset(WeaponId, FStreamableDelegate::CreateUObject( this, &AMyActor::OnWeaponLoaded));
Asset Bundle 활용

Bundle을 사용하면 상황에 따라 필요한 에셋만 선택적으로 로드할 수 있습니다. 예를 들어 "UI" 번들에는 아이콘만, "Gameplay" 번들에는 메시와 이펙트를 포함시킵니다.

DefaultGame.ini 등록 필수

Primary Asset 타입은 반드시 PrimaryAssetTypesToScan에 등록해야 Asset Manager가 인식합니다. 경로와 베이스 클래스를 정확히 지정하세요.

SUMMARY

핵심 요약

  • Hard Reference: 자동 로드, 연쇄 효과로 메모리 급증 위험
  • Soft Reference: 수동 로드, 메모리 제어 가능
  • TSoftObjectPtr: 오브젝트 Soft Reference
  • TSoftClassPtr: 클래스 Soft Reference
  • Asset Manager: Primary Asset 기반 체계적 관리
  • Reference Viewer: 의존성 그래프로 참조 관계 분석
다음 단계

다음 강의에서는 Streaming 최적화와 비동기 에셋 로딩 패턴을 다룹니다.

PRACTICE

도전 과제

배운 내용을 직접 실습해보세요

실습 1: Hard Reference 탐지

프로젝트의 주요 Actor 클래스를 Reference Viewer로 분석하여 불필요한 Hard Reference 체인을 3개 이상 찾고, TSoftObjectPtr/TSoftClassPtr로 변환하세요.

실습 2: 비동기 로드 구현

FStreamableManager::RequestAsyncLoad()를 사용하여 무기 메시를 비동기로 로드하는 시스템을 구현하세요. 로드 완료 콜백에서 StaticMesh를 컴포넌트에 할당합니다.

심화 과제

UAssetManager를 상속한 커스텀 Asset Manager를 만들어 Primary Asset 타입(Weapon, Armor)을 등록하고, Bundle 시스템으로 UI용/Gameplay용 에셋을 분리 로드하세요.