UPROPERTY ์ฌํ
๋ชจ๋ ํ๋กํผํฐ ์ง์ ์์ GC ๊ด๋ จ ํ๋๊ทธ๋ฅผ ์๋ฒฝํ๊ฒ ์ดํดํฉ๋๋ค
UPROPERTY ์ง์ ์ ์ด์ ๋ฆฌ
GC์ ์ํฅ์ ๋ฏธ์น๋ ๋ชจ๋ ํ๋กํผํฐ ์ง์ ์
GC ๊ด๋ จ ์ง์ ์
| ์ง์ ์ | GC ์ํฅ | ์ค๋ช |
|---|---|---|
UPROPERTY() | GC ์ถ์ | ๊ธฐ๋ณธ - UObject* ์ฐธ์กฐ๋ฅผ GC๊ฐ ์ถ์ |
Transient | ์ถ์ ์ ์ง | ์ง๋ ฌํ ์ ์ธ, GC ์ถ์ ์ ์ ์ง |
DuplicateTransient | ์ถ์ ์ ์ง | ๋ณต์ ์ ์ ์ธ, GC ์ถ์ ์ ์ง |
SkipSerialization | ์ถ์ ์ ์ง | ๋ชจ๋ ์ง๋ ฌํ ์ ์ธ, GC ์ถ์ ์ ์ง |
TextExportTransient | ์ถ์ ์ ์ง | ํ ์คํธ ๋ด๋ณด๋ด๊ธฐ ์ ์ธ |
NonPIEDuplicateTransient | ์ถ์ ์ ์ง | PIE ๋ณต์ ์์๋ง ๋ณต์ฌ๋จ |
Instanced | ์์ ๊ถ ์ถ์ | ์ฐธ์กฐ๊ฐ ์ธ์คํด์ค์ ์์ ๊ถ์ ๊ฐ์ง |
Export | ์์ ๊ถ ์ถ์ | Instanced์ ๋์ผ (์ปดํฌ๋ํธ์ฉ) |
UCLASS()
class UMyObject : public UObject
{
GENERATED_BODY()
// ๊ธฐ๋ณธ: GC ์ถ์ + ์ง๋ ฌํ
UPROPERTY()
UObject* StandardRef;
// GC ์ถ์ O, ์ง๋ ฌํ X (์บ์์ฉ)
UPROPERTY(Transient)
UTexture2D* CachedTexture;
// ์ธ์คํด์ค ์์ (์ด ๊ฐ์ฒด๊ฐ ํ๊ดด๋๋ฉด ์ฐธ์กฐ๋ ํ๊ดด)
UPROPERTY(Instanced)
UMySubObject* OwnedSubObject;
// ์๋ํฐ์์๋ง ์ ํจ (์ฟ ํน ์ ์ ๊ฑฐ)
UPROPERTY(Transient)
UObject* EditorOnlyCache;
};
Instanced์ ์์ ๊ถ ์๋ฏธ๋ก
UPROPERTY(Instanced)๊ฐ GC์ ๋ฏธ์น๋ ํน๋ณํ ์ํฅ
Instanced ํ๋กํผํฐ
Instanced ์ง์ ์๋ ํด๋น ์ฐธ์กฐ๊ฐ ๊ฐ์ฒด์ ์์ ๊ถ์ ๊ฐ์ง์ ์๋ฏธํฉ๋๋ค. ์์ ๊ฐ์ฒด๊ฐ ๋ณต์ ๋๋ฉด Instanced ์๋ธ์ค๋ธ์ ํธ๋ ํจ๊ป ๋ณต์ ๋ฉ๋๋ค. GC ๊ด์ ์์๋ ์ผ๋ฐ ์ฐธ์กฐ์ ๋์ผํ๊ฒ ์ถ์ ๋์ง๋ง, ์ง๋ ฌํ์ ๋ณต์ ๋์์ด ๋ค๋ฆ
๋๋ค.
// Instanced ์๋ธ์ค๋ธ์ ํธ ํจํด
UCLASS(DefaultToInstanced, EditInlineNew)
class UAbilityData : public UObject
{
GENERATED_BODY()
UPROPERTY(EditAnywhere)
float Damage = 10.f;
UPROPERTY(EditAnywhere)
float Cooldown = 1.0f;
};
UCLASS()
class AMyCharacter : public ACharacter
{
GENERATED_BODY()
// Instanced: ์บ๋ฆญํฐ๊ฐ ์์ ํ๋ ๊ณ ์ ์ธ์คํด์ค
UPROPERTY(EditAnywhere, Instanced)
UAbilityData* PrimaryAbility;
// Instanced ๋ฐฐ์ด: ๊ฐ๊ฐ ๊ณ ์ ์ธ์คํด์ค
UPROPERTY(EditAnywhere, Instanced)
TArray<UAbilityData*> Abilities;
};
// ์บ๋ฆญํฐ๊ฐ ๋ณต์ ๋๋ฉด โ AbilityData๋ ์๋ ๋ณต์
// ์บ๋ฆญํฐ๊ฐ GC๋๋ฉด โ AbilityData๋ GC ๋์
DefaultToInstanced๋ ์ด ํด๋์ค์ ๋ชจ๋ UPROPERTY ์ฐธ์กฐ๋ฅผ ์๋์ผ๋ก Instanced๋ก ๋ง๋ญ๋๋ค. EditInlineNew๋ ์๋ํฐ์์ ์ธ๋ผ์ธ์ผ๋ก ์ ์ธ์คํด์ค๋ฅผ ์์ฑํ ์ ์๊ฒ ํฉ๋๋ค. ์ด ๋ ์ง์ ์๋ฅผ ํจ๊ป ์ฌ์ฉํ๋ฉด ์๋ํฐ์์ ์๋ธ์ค๋ธ์ ํธ๋ฅผ ํธ๋ฆฌํ๊ฒ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
์ปจํ ์ด๋ ํ๋กํผํฐ์ GC
TArray, TMap, TSet ๋ด๋ถ์ UObject ์ฐธ์กฐ ์ถ์
์ปจํ ์ด๋ ๋ด๋ถ ์ฐธ์กฐ ์ถ์ ๊ท์น
UCLASS()
class UMyContainer : public UObject
{
GENERATED_BODY()
// TArray<UObject*> - ๋ชจ๋ ์์ GC ์ถ์
UPROPERTY()
TArray<AActor*> ActorList;
// TMap - Key์ Value ๋ชจ๋ ์ถ์ ๊ฐ๋ฅ
UPROPERTY()
TMap<FName, UObject*> ObjectMap;
// TMap<UObject*, UObject*> - ์์ชฝ ๋ชจ๋ ์ถ์
UPROPERTY()
TMap<UObject*, UObject*> BothSidesTracked;
// TSet<UObject*> - ๋ชจ๋ ์์ ์ถ์
UPROPERTY()
TSet<UObject*> ObjectSet;
// ์ค์ฒฉ ์ปจํ
์ด๋ - ๋ด๋ถ๊น์ง ์ถ์
UPROPERTY()
TArray<FMyStruct> StructArray;
// FMyStruct ๋ด UPROPERTY UObject*๋ ์ถ์ ๋จ
// ์ํ: UPROPERTY ์๋ ์ปจํ
์ด๋
TArray<UObject*> DangerousArray; // GC ๋ฏธ์ถ์ !
};
ํจ์ ๋ก์ปฌ ๋ณ์๋ก ์ ์ธ๋ TArray<UObject*>๋ UPROPERTY๊ฐ ์๋๋ฏ๋ก GC๊ฐ ์ถ์ ํ์ง ์์ต๋๋ค. ๋ง์ฝ ํด๋น ํจ์ ์คํ ์ค GC๊ฐ ๋ฐ์ํ๋ฉด(๋น๋๊ธฐ ์ฝ๋ฐฑ ๋ฑ), ์ปจํ
์ด๋ ๋ด์ ๊ฐ์ฒด๊ฐ ์์ง๋ ์ ์์ต๋๋ค. ์ฅ์๊ฐ ์ ์ง๋๋ ๋ก์ปฌ ์ปจํ
์ด๋์๋ FGCObject๋ฅผ ์ฌ์ฉํ๊ฑฐ๋, ๋ฉค๋ฒ ๋ณ์๋ก ์น๊ฒฉ์์ผ์ผ ํฉ๋๋ค.
UPROPERTY ๋ฉํ๋ฐ์ดํฐ์ GC ์ต์ ํ
ํ๋กํผํฐ ๋ฉํ๋ฐ์ดํฐ๊ฐ GC ํจ์จ์ ๋ฏธ์น๋ ์ํฅ
GC ํ ํฐ ์คํธ๋ฆผ ์ต์ ํ
UPROPERTY์ ํ์ ์ ๋ฐ๋ผ GC ํ ํฐ ์คํธ๋ฆผ์ ํฌ๊ธฐ์ ๋ณต์ก๋๊ฐ ๋ฌ๋ผ์ง๋๋ค. UObject ์ฐธ์กฐ๊ฐ ์๋ ํ๋กํผํฐ๋ ํ ํฐ ์คํธ๋ฆผ์ ํฌํจ๋์ง ์์ผ๋ฏ๋ก GC ์ฑ๋ฅ์ ์ํฅ์ ์ฃผ์ง ์์ต๋๋ค.
UCLASS()
class UHeavyObject : public UObject
{
GENERATED_BODY()
// GC ํ ํฐ ์์ (๊ฐ ํ์
)
UPROPERTY()
int32 Health; // ํ ํฐ ์คํธ๋ฆผ ๋ฏธํฌํจ
UPROPERTY()
FString Name; // ํ ํฐ ์คํธ๋ฆผ ๋ฏธํฌํจ
UPROPERTY()
FVector Location; // ํ ํฐ ์คํธ๋ฆผ ๋ฏธํฌํจ
// GC ํ ํฐ ์์ฑ (์ฐธ์กฐ ํ์
)
UPROPERTY()
UObject* Ref1; // GCRT_Object ํ ํฐ 1๊ฐ
UPROPERTY()
TArray<UObject*> Refs; // GCRT_ArrayObject ํ ํฐ 1๊ฐ
UPROPERTY()
TMap<FName, UObject*> Map; // GCRT_Map ํ ํฐ
};
// ์ด ํด๋์ค์ GC ํ ํฐ ์คํธ๋ฆผ = 3๊ฐ ํ ํฐ
// โ GC๊ฐ ์ด ๊ฐ์ฒด๋ฅผ ์ฒ๋ฆฌํ ๋ 3๋ฒ๋ง ๊ฒ์ฌ
UObject ์ฐธ์กฐ๋ฅผ ๋ง์ด ๊ฐ์ง ํด๋์ค๋ GC ๋น์ฉ์ด ๋์ต๋๋ค. ๋๋์ ์ฐธ์กฐ๋ฅผ ๊ด๋ฆฌํด์ผ ํ๋ค๋ฉด:
- ์ฐธ์กฐ๋ฅผ ๊ตฌ์กฐ์ฒด๋ก ๋ฌถ์ด ๊ด๋ฆฌ (ํ ํฐ ์ ๊ฐ์)
- ํ์ ์ TWeakObjectPtr ์ฌ์ฉ (GC ์ถ์ ๋ถํ์)
- ๊ฐ๋ฅํ๋ฉด TSoftObjectPtr๋ก ์ ํ (์ง์ฐ ๋ก๋ฉ)
ํต์ฌ ์์ฝ
- Transient, SkipSerialization ๋ฑ์ ์ง๋ ฌํ๋ง ์ ์ดํ๋ฉฐ GC ์ถ์ ์๋ ์ํฅ ์์ต๋๋ค
- Instanced ์ง์ ์๋ ์์ ๊ถ์ ๋ถ์ฌํ์ฌ ๋ณต์ ์ ์ง๋ ฌํ ๋์์ ๋ณ๊ฒฝํฉ๋๋ค
- TArray, TMap, TSet์ UPROPERTY ์ปจํ ์ด๋ ๋ด UObject* ์ฐธ์กฐ๋ ์๋ ์ถ์ ๋ฉ๋๋ค
- UPROPERTY๊ฐ ์๋ ๋ก์ปฌ TArray<UObject*>๋ GC๊ฐ ์ถ์ ํ์ง ๋ชปํด ์ํํฉ๋๋ค
- ๊ฐ ํ์ ํ๋กํผํฐ๋ GC ํ ํฐ ์คํธ๋ฆผ์ ํฌํจ๋์ง ์์ GC ๋น์ฉ์ด ์์ต๋๋ค
๋์ ๊ณผ์
๋ฐฐ์ด ๋ด์ฉ์ ์ง์ ์ค์ตํด๋ณด์ธ์
ํ๋์ UObject์ UPROPERTY(), UPROPERTY(Transient), raw pointer(UPROPERTY ์์), TObjectPtr ํ๋กํผํฐ๋ฅผ ๊ฐ๊ฐ ๋ง๋ค๊ณ , ์ฐธ์กฐ ๋์ ๊ฐ์ฒด์ GC ์์ง ์ฌ๋ถ๋ฅผ ํ ์คํธํ์ธ์. UPROPERTY ์๋ raw pointer๊ฐ dangling ๋๋ ์ํฉ์ ์ฌํํ์ธ์.
๊ธฐ์กด ์ฝ๋์์ UObject* raw pointer๋ฅผ ์ฌ์ฉํ๋ ํด๋์ค๋ฅผ TObjectPtr๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ์ธ์. Access Tracking๊ณผ Lazy Load ๋์์ ์ฐจ์ด๋ฅผ ๋๋ฒ๊ทธ ๋ก๊ทธ๋ก ํ์ธํ๊ณ , ๋ง์ด๊ทธ๋ ์ด์ ์ ํ ๋์์ด ๋์ผํ์ง ๊ฒ์ฆํ์ธ์.
FProperty::GetOffset_ForInternal()์ ์ฌ์ฉํ์ฌ ํด๋์ค ๋ด UPROPERTY๋ค์ ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์์ ๋ถ์ํ์ธ์. ํ๋กํผํฐ ์์, ํจ๋ฉ, ์คํ์ ์ ์๊ฐํํ๊ณ , GC๊ฐ ํ ํฐ ์คํธ๋ฆผ์ผ๋ก ์ฐธ์กฐ๋ฅผ ์ค์บํ๋ ๊ณผ์ ์ ์ดํดํ๋ ๋ฌธ์๋ฅผ ์์ฑํ์ธ์.