Weak Reference ํจํด
TWeakObjectPtr ์ฌ์ฉ๋ฒ, IsValid ํจํด, ์ํ ์ฐธ์กฐ ๋ฐฉ์ง ์ ๋ต์ ์ค์ ์์ ๋ก ํ์ตํฉ๋๋ค
TWeakObjectPtr ์ฌํ
์ฝํ ์ฐธ์กฐ์ ๋ด๋ถ ๋์๊ณผ ์์ ํ ์ฌ์ฉ ํจํด
๋ด๋ถ ๋์ ์๋ฆฌ
TWeakObjectPtr๋ GUObjectArray์ ์ธ๋ฑ์ค(ObjectIndex)์ ์๋ฆฌ์ผ ๋ฒํธ(ObjectSerialNumber)๋ฅผ ์ ์ฅํฉ๋๋ค. ์ ๊ทผ ์ ์ด ๋ ๊ฐ์ ๊ฒ์ฆํ์ฌ ๋์ ๊ฐ์ฒด์ ์ ํจ์ฑ์ ํ์ธํฉ๋๋ค.
// ์์ ํ ์ฌ์ฉ ํจํด
TWeakObjectPtr<AActor> WeakTarget;
// ํจํด 1: IsValid + Get
if (WeakTarget.IsValid())
{
AActor* Actor = WeakTarget.Get();
// ์ฃผ์: ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์๋ IsValid์ Get ์ฌ์ด์
// ๊ฐ์ฒด๊ฐ ํ๊ดด๋ ์ ์์
}
// ํจํด 2: Get + null ์ฒดํฌ (๋ ์์ )
if (AActor* Actor = WeakTarget.Get())
{
Actor->DoSomething();
}
// ํจํด 3: IsStale ์ฒดํฌ (๋ช
์์ ํ๊ดด ๊ฐ์ง)
if (WeakTarget.IsStale())
{
// ํ๋ ์ ํจํ์ง๋ง ์ด์ ํ๊ดด๋จ
// (ํ ๋ฒ๋ ํ ๋น ์ ๋ null๊ณผ ๊ตฌ๋ถ ๊ฐ๋ฅ)
}
// ๋ฆฌ์
WeakTarget.Reset(); // null๋ก ์ด๊ธฐํ
์ํ ์ฐธ์กฐ ๋ฐฉ์ง
TWeakObjectPtr๋ฅผ ํ์ฉํ ์ํ ์ฐธ์กฐ ํด๊ฒฐ ์ ๋ต
์ํ ์ฐธ์กฐ ๋ฌธ์
๋ UObject๊ฐ UPROPERTY๋ก ์๋ก๋ฅผ ์ฐธ์กฐํ๋ฉด, ๋ ๋ค Root Set์์ ๋๋ฌ ๋ถ๊ฐ๋ฅํด๋ ์๋ก์ ์ฐธ์กฐ๋ก ์ธํด GC๊ฐ ์์งํ์ง ๋ชปํฉ๋๋ค. ์ค์ ๋ก UE GC๋ ๋๋ฌ ๊ฐ๋ฅ์ฑ ๊ธฐ๋ฐ์ด๋ฏ๋ก ์ํ ์ฐธ์กฐ ์์ฒด๊ฐ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ์ผ์ผํค์ง๋ ์์ง๋ง, ์๋์น ์์ ๊ฐ์ฒด ์กด์์ ์์ธ์ด ๋ฉ๋๋ค.
// ๋ฌธ์ : ์๋ฐฉํฅ ๊ฐํ ์ฐธ์กฐ
UCLASS()
class UNodeA : public UObject
{
GENERATED_BODY()
UPROPERTY()
UNodeB* Partner; // ๊ฐํ ์ฐธ์กฐ โ B๋ฅผ ๋ณดํธ
};
UCLASS()
class UNodeB : public UObject
{
GENERATED_BODY()
UPROPERTY()
UNodeA* Partner; // ๊ฐํ ์ฐธ์กฐ โ A๋ฅผ ๋ณดํธ
};
// AโBโA ์ํ! ์ธ๋ถ ์ฐธ์กฐ ์์ด๋ ๋ ๋ค GC ์ ๋จ
// ํด๊ฒฐ: ํ ์ชฝ์ ์ฝํ ์ฐธ์กฐ๋ก
UCLASS()
class UNodeB_Fixed : public UObject
{
GENERATED_BODY()
UPROPERTY()
TWeakObjectPtr<UNodeA> Partner; // ์ฝํ ์ฐธ์กฐ โ A๋ฅผ ๋ณดํธํ์ง ์์
};
// ์ธ๋ถ ์ฐธ์กฐ ์์ผ๋ฉด โ A๊ฐ GC๋จ โ B.Partner.IsValid() == false โ B๋ GC ๊ฐ๋ฅ
UE์ Mark-Sweep GC๋ ๋๋ฌ ๊ฐ๋ฅ์ฑ(Reachability) ๊ธฐ๋ฐ์ ๋๋ค. ์ํ ์ฐธ์กฐ๊ฐ ์๋๋ผ๋ Root Set์์ ๋๋ฌ ๋ถ๊ฐ๋ฅํ๋ฉด ์ ์์ ์ผ๋ก ์์ง๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ํ ์ฐธ์กฐ ์ค ํ๋๋ผ๋ Root Set์์ ๋๋ฌ ๊ฐ๋ฅํ๋ฉด ์ ์ฒด ์ํ ๊ทธ๋ํ๊ฐ ๋ณดํธ๋ฉ๋๋ค. ๋ฌธ์ ๋ "์๋์น ์์ ๋ณดํธ"๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ๋๋ค.
Owner ํจํด๊ณผ ์ฝํ ์ญ์ฐธ์กฐ
์์ ์-ํผ์์ ์ ๊ด๊ณ์์์ ์ฐธ์กฐ ๋ฐฉํฅ ์ค๊ณ
Owner ํจํด
๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ํจํด์ ์์ ์๋ ๊ฐํ ์ฐธ์กฐ๋ก ํผ์์ ์๋ฅผ ์ฐธ์กฐํ๊ณ , ํผ์์ ์๋ ์ฝํ ์ฐธ์กฐ๋ก ์์ ์๋ฅผ ์ญ์ฐธ์กฐํ๋ ๊ฒ์ ๋๋ค.
// Owner ํจํด ์์
UCLASS()
class UInventory : public UObject
{
GENERATED_BODY()
// ์์ ์: ๊ฐํ ์ฐธ์กฐ๋ก ์์ดํ
๋ณด์
UPROPERTY()
TArray<UItem*> Items;
// ์์ ์: ๊ฐํ ์ฐธ์กฐ๋ก ์บ๋ฆญํฐ ์ฐธ์กฐ
UPROPERTY()
TObjectPtr<ACharacter> OwnerCharacter;
};
UCLASS()
class UItem : public UObject
{
GENERATED_BODY()
// ํผ์์ ์: ์ฝํ ์ฐธ์กฐ๋ก ์ธ๋ฒคํ ๋ฆฌ ์ญ์ฐธ์กฐ
UPROPERTY()
TWeakObjectPtr<UInventory> OwningInventory;
void Use()
{
if (UInventory* Inv = OwningInventory.Get())
{
Inv->ConsumeItem(this);
}
}
};
์ฐธ์กฐ ๋ฐฉํฅ ์ค๊ณ ์์น
| ๊ด๊ณ | ์์ ์ โ ํผ์์ ์ | ํผ์์ ์ โ ์์ ์ |
|---|---|---|
| ๋ถ๋ชจ-์์ | UPROPERTY (๊ฐํ) | TWeakObjectPtr (์ฝํ) |
| ์ปดํฌ๋ํธ-์กํฐ | ์๋ (Component) | GetOwner() ๋ด์ฅ |
| ์์ ฏ-๋ฐ์ดํฐ | UPROPERTY (๊ฐํ) | TWeakObjectPtr (์ฝํ) |
| AI-ํ๊ฒ | TWeakObjectPtr (์ฝํ) | - |
์ค์ ์ฝํ ์ฐธ์กฐ ์ฌ์ฉ ์ฌ๋ก
๊ฒ์ ๊ฐ๋ฐ์์ ์์ฃผ ๋ง๋๋ ์ฝํ ์ฐธ์กฐ ํจํด
๋ธ๋ฆฌ๊ฒ์ดํธ์ ์ฝํ ์ฐธ์กฐ
// ํ์ด๋จธ ์ฝ๋ฐฑ์ ์ฝํ ์ฐธ์กฐ ํจํด
TWeakObjectPtr<AActor> WeakTarget = TargetActor;
GetWorld()->GetTimerManager().SetTimer(
TimerHandle,
[WeakTarget]()
{
if (AActor* Target = WeakTarget.Get())
{
Target->ApplyDamage(10.f);
}
// WeakTarget์ด ๋ฌดํจ๋ฉด ์๋ฌด๊ฒ๋ ์ ํจ (์์ )
},
2.0f,
false
);
// ๋ฉํฐ์บ์คํธ ๋ธ๋ฆฌ๊ฒ์ดํธ์์์ ํจํด
OnEnemyDefeated.AddWeakLambda(this,
[this](AActor* DefeatedEnemy)
{
// this๊ฐ ํ๊ดด๋๋ฉด ์๋์ผ๋ก ๋ฐ์ธ๋ฉ ํด์
Score += 100;
}
);
// UI์์์ ์ฝํ ์ฐธ์กฐ
UPROPERTY()
TWeakObjectPtr<APlayerController> WeakPC;
// ์์ ฏ์ด PC๋ณด๋ค ์ค๋ ์ด ์ ์์ผ๋ฏ๋ก ์ฝํ ์ฐธ์กฐ ์ฌ์ฉ
ํต์ฌ ์์ฝ
- TWeakObjectPtr๋ ObjectIndex์ SerialNumber๋ก ์์ ํ๊ฒ ์ ํจ์ฑ์ ๊ฒ์ฆํฉ๋๋ค
- ์๋ฐฉํฅ ๊ฐํ ์ฐธ์กฐ์ ์ํ ๋ฌธ์ ๋ ํ ์ชฝ์ TWeakObjectPtr๋ก ๋ณ๊ฒฝํ์ฌ ํด๊ฒฐํฉ๋๋ค
- Owner ํจํด: ์์ ์๋ ๊ฐํ ์ฐธ์กฐ, ํผ์์ ์๋ ์ฝํ ์ญ์ฐธ์กฐ๊ฐ ํ์ค์ ๋๋ค
- ํ์ด๋จธ, ๋ธ๋ฆฌ๊ฒ์ดํธ ๋ฑ ๋น๋๊ธฐ ์ฝ๋ฐฑ์์๋ ๋ฐ๋์ ์ฝํ ์ฐธ์กฐ๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค
- UE GC๋ ๋๋ฌ ๊ฐ๋ฅ์ฑ ๊ธฐ๋ฐ์ด๋ฏ๋ก ์ํ ์์ฒด๋ ๋ฌธ์ ๊ฐ ์๋์ง๋ง, ์๋์น ์์ ๋ณดํธ๋ฅผ ์ฃผ์ํด์ผ ํฉ๋๋ค
๋์ ๊ณผ์
๋ฐฐ์ด ๋ด์ฉ์ ์ง์ ์ค์ตํด๋ณด์ธ์
TWeakObjectPtr์ ์ฌ์ฉํ ๊ฐ์ฒด ์บ์ ์์คํ ์ ๊ตฌํํ์ธ์. ์บ์๋ ๊ฐ์ฒด๊ฐ GC๋๋ฉด ์๋์ผ๋ก ๊ฐ์งํ์ฌ ์ฌ์์ฑํ๋ ํจํด์ ๋ง๋ค๊ณ , ๊ฐํ ์ฐธ์กฐ ์บ์์์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ์ฐจ์ด๋ฅผ ๋น๊ตํ์ธ์.
TSoftObjectPtr๋ก ์์ ์ ์ฐธ์กฐํ๊ณ , ํ์ํ ์์ ์ LoadSynchronous() ๋๋ ๋น๋๊ธฐ ๋ก๋(FStreamableManager)๋ก ์ค์ ๋ก๋ฉํ๋ ํจํด์ ๊ตฌํํ์ธ์. ๋ก๋/์ธ๋ก๋ ์ฌ์ดํด์์ GC ๋์์ ํ์ธํ์ธ์.
TWeakObjectPtr์ ํ์ฉํ์ฌ ๊ตฌ๋ ์๊ฐ GC๋๋ฉด ์๋์ผ๋ก ๊ตฌ๋ ์ด ํด์ ๋๋ ์์ ํ ์ด๋ฒคํธ/๋ธ๋ฆฌ๊ฒ์ดํธ ์์คํ ์ ๊ตฌํํ์ธ์. ์ผ๋ฐ DECLARE_DYNAMIC_MULTICAST_DELEGATE์ ๋น๊ตํ์ฌ ๋ฉ๋ชจ๋ฆฌ ์์ ์ฑ ์ฐจ์ด๋ฅผ ๋ถ์ํ์ธ์.