언리얼 Hard Reference vs Soft Reference

민트맛치킨·2025년 10월 24일

Unreal

목록 보기
16/26

Hard Reference

  • UPROPERTY로 직접 선언하는 포인터 참조 방식
  • 참조하는 오브젝트가 로드될 때 참조된 에셋도 자동으로 메모리에 함께 로드
  • 별도의 로딩 코드 없이 바로 사용 가능
  • 참조 체인(Reference Chain)을 따라 연결된 모든 에셋이 함께 로딩됨
  • 사용 예시: UPROPERTY() UStaticMesh* MyMesh;

장점

  • 코드 작성이 간단하고 직관적
  • 에셋을 즉시 사용할 수 있어 런타임 로딩 지연 없음
  • Null 체크만으로 간단하게 에러 처리 가능

단점

  • 불필요한 에셋까지 메모리에 로드되어 메모리 낭비 발생
  • 초기 로딩 시간이 길어질 수 있음
  • 참조 체인이 복잡해지면 의도치 않은 대량의 에셋 로딩 발생

Soft Reference

  • TSoftObjectPtr, TSoftClassPtr, FSoftObjectPath 등을 사용한 간접 참조 방식
  • 에셋의 경로 정보만 저장하고 실제 에셋은 메모리에 로드하지 않음
  • 필요한 시점에 명시적으로 로딩해야 사용 가능
  • 비동기 로딩(AsyncLoad)과 동기 로딩(LoadSynchronous) 지원
  • 사용 예시: UPROPERTY() TSoftObjectPtr<UStaticMesh> MyMesh;

장점

  • 초기 메모리 사용량을 크게 절감
  • 필요한 시점에만 로딩하여 메모리 효율적 관리
  • 로딩 타이밍을 개발자가 제어 가능
  • 대규모 프로젝트의 성능 최적화에 필수적

단점

  • 로딩 코드를 직접 작성해야 함
  • 비동기 로딩 시 콜백 처리 등 복잡도 증가
  • 에셋이 로드되지 않은 상태에서 접근 시 Null 처리 필요

Hard Reference를 사용하는 경우

  • 항상 필요한 필수 에셋 (예: 캐릭터의 기본 메시)
  • 작은 용량의 에셋
  • 프로토타입 단계에서 빠른 개발이 필요할 때

Soft Reference를 사용하는 경우

  • 조건부로 사용되는 에셋 (예: 스킬 이펙트, UI 위젯)
  • 대용량 에셋 (예: 시네마틱 영상, 고해상도 텍스처)
  • 레벨 스트리밍이나 DLC 콘텐츠
  • 메모리 최적화가 중요한 모바일/콘솔 플랫폼

Hard Reference vs Soft Reference 비교

구분Hard ReferenceSoft Reference
선언 방식UPROPERTY() UClass*UPROPERTY() TSoftObjectPtr<UClass>
로딩 시점자동 로딩 (오브젝트 로드 시)명시적 로딩 필요
메모리 사용참조 체인 전체 로딩 (높음)필요한 것만 로딩 (낮음)
초기 로딩 속도느림 (연결된 모든 에셋 로딩)빠름 (경로만 저장)
사용 편의성높음 (바로 사용 가능)낮음 (로딩 코드 필요)
런타임 성능즉시 접근 가능로딩 대기 필요
메모리 최적화어려움용이함
적합한 상황필수 에셋, 작은 에셋조건부 사용, 대용량 에셋
로딩 제어불가능 (자동)가능 (AsyncLoad/Sync)

코드 예시

Hard Reference

UPROPERTY(EditAnywhere, BlueprintReadWrite)
UStaticMesh* WeaponMesh;  // 자동으로 로드됨

void UseWeapon()
{
    if (WeaponMesh)  // 바로 사용 가능
    {
        // 즉시 사용
    }
}

Soft Reference

UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSoftObjectPtr<UStaticMesh> WeaponMesh;  // 경로만 저장

void LoadAndUseWeapon()
{
    // 비동기 로딩
    FStreamableManager& Streamable = UAssetManager::GetStreamableManager();
    Streamable.RequestAsyncLoad(WeaponMesh.ToSoftObjectPath(), 
        FStreamableDelegate::CreateLambda([this]()
        {
            if (UStaticMesh* LoadedMesh = WeaponMesh.Get())
            {
                // 로딩 완료 후 사용
            }
        })
    );
}

동기 로딩 (Synchronous Loading)

  • 에셋 로딩이 완료될 때까지 게임이 멈춤 (블로킹)
  • 로딩이 끝나야 다음 코드가 실행됨
  • 사용법: LoadSynchronous(), LoadObject(), StaticLoadObject()
  • 구현이 간단하지만 프레임 드랍(Frame Drop) 발생 위험
  • 로딩 시간이 길면 게임이 얼어붙은 것처럼 보임

동기 로딩을 사용하는 경우

  • 로딩 화면이 표시되는 동안
  • 게임 초기화 단계
  • 레벨 전환 시
  • 작은 용량의 에셋을 즉시 필요로 할 때

코드 예시

// 동기 로딩 - 로딩이 끝날 때까지 대기
UStaticMesh* LoadedMesh = WeaponMeshSoft.LoadSynchronous();
if (LoadedMesh)
{
    // 바로 사용 가능
    SetStaticMesh(LoadedMesh);
}

비동기 로딩 (Asynchronous Loading)

  • 백그라운드에서 로딩하면서 게임은 계속 실행됨 (논블로킹)
  • 로딩 완료 시 콜백 함수가 호출됨
  • 사용법: RequestAsyncLoad(), FStreamableManager, LoadAsync()
  • 구현이 복잡하지만 부드러운 게임플레이 유지 가능
  • 프레임 저하 없이 에셋을 로딩할 수 있음

비동기 로딩을 사용하는 경우

  • 게임플레이 도중 에셋 로딩
  • 레벨 스트리밍 (Level Streaming)
  • 대용량 에셋 로딩
  • 사용자 경험을 해치지 않아야 할 때

코드 예시

// 비동기 로딩 - 게임은 계속 진행
FStreamableManager& Streamable = UAssetManager::GetStreamableManager();
TSharedPtr Handle = Streamable.RequestAsyncLoad(
    WeaponMeshSoft.ToSoftObjectPath(),
    [this]()
    {
        // 로딩 완료 후 콜백에서 처리
        if (UStaticMesh* LoadedMesh = WeaponMeshSoft.Get())
        {
            SetStaticMesh(LoadedMesh);
        }
    }
);

0개의 댓글