하드/소프트 레퍼런스

주상돈·2025년 2월 18일

TIL

목록 보기
31/53

  • 언리얼 엔진5 에서 기본 제공하는 스마트 포인터는 일반적인 클래스를 다루는 STL의 C++에서 제공하는 스마트 포인터와 유사한 동작과 쓰임을 제공 한다.
  • 하지만 만약 UObject에 스마트 포인터 변수가 멤버 변수로서 선언된다면?
    • 이 경우, UObject가 사라지기 전까지는 레퍼런스 카운트가 0이 된다고 하여 스마트 포인터의 메모리를 해제하지 않는다.
  • 위의 그림처럼 UObject 에서 상속 받은 클래스에 나의 클래스를 멤버로 둔다. 하지만 레퍼런스 카운트가 0이 되어도 메모리에서는 사라지지 않는다. 가비지 컬렉터에서 UObject를 제거해야 비로서 메모리 해제가 이뤄진다.
  • 이러한 경우를 위해 필요한 이해가 리소스 관리시 하드 레퍼런스와 소프트 레퍼런스의 개념 이해이다..

Hard Reference vs Soft Reference

  • 언리얼 엔진에서는 엔지니어에게 메모리 효율을 스스로 관리할 수 있도록 위 두 가지(하드 혹은 소프트 레퍼런스) 제공.
  • 이를 활용하여 아래와 같은 조절이 가능하다
    • 로딩된 전체 메모리 양의 관리를 자동 혹은 수동으로 관리하게 함.
    • 위 둘을 적절히 혼합하여 성능 효율을 기대할 수 있음
    • 부담 되는 로딩 시간을 위 테크닉을 사용하여 적절히 분배 가능.

하드 레퍼런스 포인터 종류와 특징

하드 레퍼런스는 말 그대로 항상 로드되며, 리소스 혹은 오브젝트 해당하는 메모리 공간을 수동으로 내려주지 않는다면 계속 상주하게 된다는 것을 의미합니다. 이말은 다시 말해 GC(Garbage Collector)의 대상에서 빠진다는 것과 동일.
아래는 하드 레퍼런스의 종류입니다.

  • UPROPERTY 를 사용하여 선언된 오브젝트

    UPROPERTY(...)
    UStaticMeshComponent *MeshComp;
  • TObjectPtr

    • 위의 UPROPERTY()와 Raw 포인터 사용한 것과 동일한 형태를 띄지만, 스마트 포인터의 장점(nullptr 과 dangling 방지)을 취할 수 있다.
    • UPROPERTY 처럼 리플렉션 속성도 일반포인터 처럼 설정 할 수 있다.
  • TStrongObjectPtr

    • UPROPERTY 처럼 리플랙션 속성을 명시적으로 받아가기 원하지 않는 경우만 사용합니다.
    • 나머지는 TObjectPtr과 동일.
  • 특징

    • 게임 로딩이나 레벨 로딩시 같이 메모리에 로드 되므로 중간 끊김이 없음.
    • 항상 로드되어 존재하므로 메모리 사용량이 증가하며, 따로 관리하지 않으면 메모리에 계속 남아있게 됨.
    • 언리얼 레벨에 속해있는 하드 레퍼런스 오브젝트의 경우 레벨과 같이 로드/언로드 됨.

하드 레퍼런스는 무슨 용도로 사용해야 할까?

  • 플레이어와 관련 된 것 등(= 항상 로딩 되어야 하는 필요한 오브젝트)
    • PlayerController, Player Chracter, Game State, etc
    • 플레이어가 이동시 필요한 지형과 상호작용이 필요한 오브젝트들
    • 그외 게임 플레이와 관련된 모든 요소 모두 포함.
  • 언제나 보여야 하는 의미있는 오브젝트들
    • 거대한 시각적 리소스이지만, 만약 게임 플레이에 의미있는 오브젝트라면 미리 로딩 해놓아야 게임 플레이어가 인지하고 활용할 수 있음.

우리가 현재 프로젝트와 함께 사용 중인 리소스는 모두 하드 레퍼런스 사용 중.

소프트 레퍼런스의 종류와 특징

  • 타입 종류
    • TSoftObjectPtr, TWeakObjectPtr, FSoftObjectPath
      • 중간에 Object 단어가 들어간 이유는 위에서 언급된 스마트 포인터에 비해 UObject에서 상속된 객체 전용으로 디자인되어 있기 때문.
  • 비동기(Asynchronous) 로딩 지원
    • 로딩시 블럭 되지 않음 → 게임 스레드를 멈추지 않음
  • DLCs 나 레벨 스트리밍에 주로 이용
  • 단점
    • 수동으로 로딩을 관리해줘야 함. 자동으로 로딩되지 않음.

    • LoadSynchronous() 를 명시적으로 호출해줘야 로딩됨.

      TSoftObjectPtr<UTexture2D> SoftTexture = TSoftObjectPtr<UTexture2D>(FSoftObjectPath(TEXT("/Game/Textures/MyTexture")));
      UTexture2D* LoadedTexture = SoftTexture.LoadSynchronous()
    • 해제 시에는 다음과 같은 코드 형태.

      FStreamableManager& StreamableManager = UAssetManager::GetStreamableManager();
      StreamableManager.Unload(SoftTexture.ToSoftObjectPath());
      
      // 필요에 따라 명시적인 GC 호출이 필요하기도 함.
      CollectGarbage(GARBAGE_COLLECTION_KEEPFLAGS);
    • 잘 관리하지 않으면 프레임 드랍 발생 가능(Frame hitches)

    • 스트링 기반 리소스 경로 의존적이라 경로가 바뀌면 따로 관리해 주는 안전 장치가 필요.

      • 에디터상에서 유효성 체크 안해 줌.

0개의 댓글