
- 언리얼 엔진5 에서 기본 제공하는 스마트 포인터는 일반적인 클래스를 다루는 STL의 C++에서 제공하는 스마트 포인터와 유사한 동작과 쓰임을 제공 한다.
- 하지만 만약 UObject에 스마트 포인터 변수가 멤버 변수로서 선언된다면?
- 이 경우, UObject가 사라지기 전까지는 레퍼런스 카운트가 0이 된다고 하여 스마트 포인터의 메모리를 해제하지 않는다.
- 위의 그림처럼 UObject 에서 상속 받은 클래스에 나의 클래스를 멤버로 둔다. 하지만 레퍼런스 카운트가 0이 되어도 메모리에서는 사라지지 않는다. 가비지 컬렉터에서 UObject를 제거해야 비로서 메모리 해제가 이뤄진다.
- 이러한 경우를 위해 필요한 이해가 리소스 관리시 하드 레퍼런스와 소프트 레퍼런스의 개념 이해이다..
Hard Reference vs Soft Reference
- 언리얼 엔진에서는 엔지니어에게 메모리 효율을 스스로 관리할 수 있도록 위 두 가지(하드 혹은 소프트 레퍼런스) 제공.
- 이를 활용하여 아래와 같은 조절이 가능하다
- 로딩된 전체 메모리 양의 관리를 자동 혹은 수동으로 관리하게 함.
- 위 둘을 적절히 혼합하여 성능 효율을 기대할 수 있음
- 부담 되는 로딩 시간을 위 테크닉을 사용하여 적절히 분배 가능.
하드 레퍼런스 포인터 종류와 특징
하드 레퍼런스는 말 그대로 항상 로드되며, 리소스 혹은 오브젝트 해당하는 메모리 공간을 수동으로 내려주지 않는다면 계속 상주하게 된다는 것을 의미합니다. 이말은 다시 말해 GC(Garbage Collector)의 대상에서 빠진다는 것과 동일.
아래는 하드 레퍼런스의 종류입니다.
하드 레퍼런스는 무슨 용도로 사용해야 할까?
- 플레이어와 관련 된 것 등(= 항상 로딩 되어야 하는 필요한 오브젝트)
- 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());
CollectGarbage(GARBAGE_COLLECTION_KEEPFLAGS);
-
잘 관리하지 않으면 프레임 드랍 발생 가능(Frame hitches)
-
스트링 기반 리소스 경로 의존적이라 경로가 바뀌면 따로 관리해 주는 안전 장치가 필요.