안선생의 개발 블로그
[UE5] TWeakObjetPtr 본문
TWeakObjetPtr는 참조 받을 때 사용합니다.
공식문서를 보면
UProperty 가 아닌 오브젝트 포인터가 필요한 경우, TWeakObjectPtr 사용을 고려해 보세요. 이는 약 포인터로, 가비지 컬렉션을 방지하지는 않지만, 접근 전 질의를 통해 유효성 검사가 가능하며, 거기서 가리키는 오브젝트가 소멸된 경우 null 설정도 가능합니다.
즉 우리는 UPROPERTY매크로를 통해 가비지 컬렉션을 방지할 수 있습니다. UPROPERTY매크로가 루트셋에 참조하기 때문 하지만 우리가 UPROPERTY매크로를 사용하지 않고 오브젝트를 얻고 싶으면 rowPoint대신 TWeakObjectPtr을 사용해야 합니다.
아래 예제보겠습니다.
//..h
class ATestActor* RowTestActor;
UPROPERTY()
class ATestActor* UPROPERTYTestActor;
TWeakObjectPtr<ATestActor> TWeakObjectTestActor;
}
//. cpp
void ATistoryCharacter::BeginPlay()
{
FActorSpawnParameters Params;
UPROPERTYTestActor = GetWorld()->SpawnActor<ATestActor>(Params);
RowTestActor = UPROPERTYTestActor;
TWeakObjectTestActor = UPROPERTYTestActor;
if (TWeakObjectTestActor.IsValid())
{
UE_LOG(LogTemp, Error, TEXT("TWeakObjectTestActor data : %d"), TWeakObjectTestActor->Data);
}
else
{
UE_LOG(LogTemp, Error, TEXT("TWeakObjectTestActor is nullptr"));
}
if (RowTestActor != nullptr)
{
UE_LOG(LogTemp, Error, TEXT("RowTestActor data : %d"), RowTestActor->Data);
}
else
{
UE_LOG(LogTemp, Error, TEXT("RowTestActor is nullptr"));
}
if (UPROPERTYTestActor != nullptr)
{
UE_LOG(LogTemp, Error, TEXT("UPROPERTYTestActor data : %d"), UPROPERTYTestActor->Data);
}
else
{
UE_LOG(LogTemp, Error, TEXT("UPROPERTYTestActor is nullptr"));
}
UPROPERTYTestActor->Destroy();
GEngine->ForceGarbageCollection(true);
if (TWeakObjectTestActor.IsValid())
{
UE_LOG(LogTemp, Error, TEXT("TWeakObjectTestActor data : %d"), TWeakObjectTestActor->Data);
}
else
{
UE_LOG(LogTemp, Error, TEXT("TWeakObjectTestActor is nullptr"));
}
if (RowTestActor != nullptr)
{
UE_LOG(LogTemp, Error, TEXT("RowTestActor data : %d"), RowTestActor->Data);
}
else
{
UE_LOG(LogTemp, Error, TEXT("RowTestActor is nullptr"));
}
if (UPROPERTYTestActor != nullptr)
{
UE_LOG(LogTemp, Error, TEXT("UPROPERTYTestActor data : %d"), UPROPERTYTestActor->Data);
}
else
{
UE_LOG(LogTemp, Error, TEXT("UPROPERTYTestActor is nullptr"));
}
}
../TIck
void ATistoryCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (TWeakObjectTestActor.IsValid())
{
UE_LOG(LogTemp, Error, TEXT("TWeakObjectTestActor data : %d"), TWeakObjectTestActor->Data);
}
else
{
UE_LOG(LogTemp, Error, TEXT("TWeakObjectTestActor is nullptr"));
}
if (RowTestActor != nullptr)
{
UE_LOG(LogTemp, Error, TEXT("RowTestActor data : %d"), RowTestActor->Data);
}
else
{
UE_LOG(LogTemp, Error, TEXT("RowTestActor is nullptr"));
}
if (UPROPERTYTestActor != nullptr)
{
UE_LOG(LogTemp, Error, TEXT("UPROPERTYTestActor data : %d"), UPROPERTYTestActor->Data);
}
else
{
UE_LOG(LogTemp, Error, TEXT("UPROPERTYTestActor is nullptr"));
}
}
1. 위에 간단합니다.액터를 스폰하고 Row포인터와 Weak포인터를 스폰한 액터를 참조합니다. 그후 데이터 값을 출력합니다.
2. 참조한 액터 Destroy하고 GC를 강제로 실행시킵니다.
3. Tick함수를 계속 확인합니다.
실행결과
1. Beginplay처음에는 모든 포인터에 데이터가 있는것을 알 수 있음
2. Destroy , GC강제 실행후 TWeakObjetPtr은 데이터가 없는것을 알 수 있음
3. Tick함수 실행시 가비지컬렉션으로 인한 UPROPERTY()매크로 포인터와 Weak포인터는 메모리가 해제 됐지만 Row포인터는 아직도 가리키는것을 알 수 있음(댕글링 포인터)
디버그
RowPointer
TWeakObjectPtr
UPROPERTY
RowPointer만 주소값을 가지고 있음 하지만 참조 대상 메모리는 해제되있는것을 볼 수 있다.
IsValid로 검사한 결과
IsValid는 객체가 존재하는지 확인 삭제된걸 바로 알 수 있음 Destroy를 확일할거면 IsValid를 쓰자
다른 포인터가 TWeakObjectPtr를 참조할라 할 때
에러가 뜸
요약
1. Object를 참조할 때는 TWeakObjectPtr을 쓰거나 UPROPRETY를 쓰자
2. TWeakObjectPtr는 가비지컬렉션을 방지하는게 아닌 참조대상이 유휴한지 확인 할 수 있음
3. UPROPERTY매크로는 포인터를 소멸시키는 경우 자동으로 nullptr 이 됨
4. RowPoint는 GC로 인해 메모리는 해제되지만 댕글링 포인터(Dangling pointer)을 이르킴
5. IsValid로 객체는 존재하지 않지만 Row포인터는 무언가를 가르키고있음
5. 객체가 파괴된지 확인할라면 IsValid를 쓰자.
6. TWeakObjectPtr를 다른 포인터가 참조 할 수 없다.
아래 사이트 참조 했습니다.
https://chogyujin-study.tistory.com/72
언리얼 엔진의 가비지 컬렉션
오늘은 언리얼 엔진의 가비지 컬렉션에 대해 공부하겠습니다. 1. 가비지 컬렉션? 가비지 컬렉션이란 메모리를 관리해주는 시스템으로 C#, JAVA 등 언어에는 기본적으로 가지고 있는 시스템입니다.
chogyujin-study.tistory.com
'언리얼' 카테고리의 다른 글
[UE5] 언리얼 가비지 컬렉션 (0) | 2023.12.09 |
---|---|
[UE5] 언리얼 스마트 포인터 (0) | 2023.12.03 |
[UE5] 애니메이션 블루프린트 (0) | 2023.11.13 |
[UE5] Cast (0) | 2023.11.11 |
[UE5] 액터 스폰하기 (0) | 2023.11.06 |