콘텐츠로 이동

UE5 가비지 컬렉션 시스템

UE5는 .NET/Java처럼 자동 GC를 제공하지만, UObject를 상속하는 클래스에만 적용됩니다. UObject가 아닌 일반 C++ 객체는 new/delete로 수동 관리합니다.

GC 동작:

  1. 마킹: 루트셋(Root Set)에서 도달 가능한 모든 UObject 탐색
  2. 스위핑: 도달 불가 UObject를 ConditionalBeginDestroy() 호출 후 삭제
// UPROPERTY()가 없으면 GC가 수집할 수 있음
UCLASS()
class AMyActor : public AActor {
GENERATED_BODY()
// GC에 의해 추적됨 (안전)
UPROPERTY()
UMyComponent* SafeComponent;
// GC에 의해 추적되지 않음 (위험)
UMyComponent* UnsafeComponent; // 수집 후 dangling pointer!
};

항상 UObject 포인터 멤버에는 UPROPERTY()를 붙이세요.

UObject를 GC에서 영구 보호합니다.

// GC 수집 방지 (전역 싱글턴, 플러그인 등)
MyObject->AddToRoot();
// 보호 해제 (메모리 누수 주의)
MyObject->RemoveFromRoot();
// 루트에 있는지 확인
if (MyObject->IsRooted()) { ... }

GC가 객체를 수집해도 dangling pointer가 되지 않고 nullptr이 됩니다.

TWeakObjectPtr<AActor> WeakTarget;
void SetTarget(AActor* Target) {
WeakTarget = Target;
}
void Update() {
// Get()으로 유효성 확인
if (AActor* Target = WeakTarget.Get()) {
// 유효한 경우에만 사용
FVector Dir = Target->GetActorLocation();
}
// WeakTarget.IsValid() 도 사용 가능
}

UPROPERTY()와 함께 사용하는 타입 안전 포인터입니다.

UPROPERTY()
TObjectPtr<UStaticMeshComponent> MeshComp;
// 할당
MeshComp = CreateDefaultSubobject<UStaticMeshComponent>("Mesh");
// nullptr 체크
if (IsValid(MeshComp)) { ... }
[/Script/Engine.GarbageCollectionSettings]
// GC 주기 설정 (초, 기본값 60초)
// DefaultEngine.ini:
// gc.TimeBetweenPurgingPendingKillObjects=30
// 코드에서 강제 GC (씬 전환 등에 사용)
GEngine->ForceGarbageCollection(true);
// 비동기 GC (덜 블로킹)
if (GEngine)
GEngine->ForceGarbageCollection(false);
// 잘못된 방법: nullptr만 체크하면 pending kill 상태 놓침
if (MyActor != nullptr) { MyActor->DoSomething(); } // 위험
// 올바른 방법: IsValid()로 pending kill 포함 검사
if (IsValid(MyActor)) { MyActor->DoSomething(); }
// 또는
if (MyActor && !MyActor->IsPendingKill()) { ... }

일반 구조체/클래스의 메모리 관리

섹션 제목: “일반 구조체/클래스의 메모리 관리”
// UObject가 아닌 클래스는 스마트 포인터 사용
TSharedPtr<FMyData> SharedData = MakeShared<FMyData>();
TUniquePtr<FMyHelper> Helper = MakeUnique<FMyHelper>();
TWeakPtr<FMyData> WeakRef = SharedData;
// 게임플레이 코드: TSharedPtr 남용 주의 (스레드 안전 오버헤드)
// 단일 소유권: TUniquePtr
// 공유 소유권: TSharedPtr
  • UPROPERTY()가 없는 UObject 포인터는 GC 대상 — 반드시 붙일 것
  • TWeakObjectPtr로 소유 없는 참조, IsValid()로 항상 유효성 검사
  • AddToRoot는 전역 싱글턴 등 예외적 경우에만 사용 (누수 주의)
  • 씬 전환 후 ForceGarbageCollection으로 메모리 즉시 해제
  • UObject가 아닌 객체는 TUniquePtr / TSharedPtr로 관리