PART 6 Β· κ°•μ˜ 3/4

Editor vs Runtime GC

PIE νŠΉμˆ˜μ„±, Editor Only 객체, 에디터 λ©”λͺ¨λ¦¬ κ΄€λ¦¬μ˜ GC 차이λ₯Ό μ΄ν•΄ν•©λ‹ˆλ‹€

SECTION 01

에디터와 λŸ°νƒ€μž„ GC 차이

에디터 ν™˜κ²½μ—μ„œμ˜ GC λ™μž‘ νŠΉμ„±

μ£Όμš” 차이점

ν•­λͺ©μ—λ””ν„°λŸ°νƒ€μž„ (Shipping)
MaxObjects12,582,9122,162,688
TObjectPtr λ™μž‘μ§€μ—° λ‘œλ”© + μ ‘κ·Ό 좔적raw 포인터와 동일
UObject 수맀우 많음 (에셋 메타데이터)μƒλŒ€μ μœΌλ‘œ 적음
GC λΉˆλ„μ‚¬μš©μž λ™μž‘μ— 의쑴gc.TimeBetween... 기반
Undo/Redo 영ν–₯νŠΈλžœμž­μ…˜ 객체 λ³΄κ΄€μ—†μŒ
RF_Standalone에셋 λ³΄ν˜Έμ— μ‚¬μš©κ±°μ˜ μ‚¬μš© μ•ˆ 함
μ—λ””ν„°μ—μ„œ λ©”λͺ¨λ¦¬κ°€ 더 많이 ν•„μš”ν•œ 이유

μ—λ””ν„°λŠ” λͺ¨λ“  μ—μ…‹μ˜ 메타데이터, 썸넀일, 에디터 μ „μš© ν”„λ‘œνΌν‹°λ₯Ό λ©”λͺ¨λ¦¬μ— μœ μ§€ν•©λ‹ˆλ‹€. λ˜ν•œ Undo/Redoλ₯Ό μœ„ν•œ νŠΈλžœμž­μ…˜ νžˆμŠ€ν† λ¦¬λ„ GC Root에 μ—°κ²°λ˜μ–΄ λ©”λͺ¨λ¦¬λ₯Ό μ°¨μ§€ν•©λ‹ˆλ‹€. μ—λ””ν„°μ—μ„œμ˜ λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ€ λŸ°νƒ€μž„μ˜ 3~5λ°°κ°€ 될 수 μžˆμŠ΅λ‹ˆλ‹€.

SECTION 02

PIE(Play In Editor) GC νŠΉμˆ˜μ„±

PIE λͺ¨λ“œμ—μ„œμ˜ GC μ£Όμ˜μ‚¬ν•­

PIE와 에디터 곡쑴

C++ // PIEμ—μ„œ GCκ°€ λ‹€λ₯΄κ²Œ λ™μž‘ν•˜λŠ” 점: 1. μ›”λ“œ 뢄리 에디터 μ›”λ“œμ™€ PIE μ›”λ“œκ°€ λ™μ‹œ 쑴재 각 μ›”λ“œμ˜ κ°μ²΄λŠ” λ…λ¦½μ μœΌλ‘œ GC λŒ€μƒ 2. PIE μ’…λ£Œ μ‹œ GC PIE μ’…λ£Œ β†’ κ²Œμž„ μ›”λ“œμ˜ λͺ¨λ“  객체 파괴 λŒ€λŸ‰ GC λ°œμƒ β†’ 에디터 μž μ‹œ 멈좀 3. PIEμ—μ„œ Standaloneκ³Ό λ‹€λ₯Έ λ™μž‘ // PIEμ—μ„œλ§Œ λ°œμƒν•˜λŠ” 문제: // - 에디터 에셋을 직접 μ°Έμ‘°ν•˜λ©΄ PIE μ’…λ£Œ 후에도 λ‚¨μŒ // - NonPIEDuplicateTransient둜 μ œμ–΄ // PIE 감지 if (GEngine->IsEditor()) { if (GWorld->IsPlayInEditor()) { // PIE ν™˜κ²½ } } // PIEμ—μ„œ 에셋 볡제 μ—¬λΆ€ 확인 UPROPERTY(NonPIEDuplicateTransient) UObject* EditorOnlyRef; // PIE μ‹œμž‘ μ‹œ 이 ν”„λ‘œνΌν‹°λŠ” 볡제됨 // Standalone κ²Œμž„μ—μ„œλŠ” 볡제 μ•ˆ 됨
SECTION 03

Editor Only 객체와 μΏ ν‚Ή

#if WITH_EDITOR와 에디터 μ „μš© UObject 관리

에디터 μ „μš© 객체의 GC

C++ UCLASS() class UMyData : public UObject { GENERATED_BODY() // μ—λ””ν„°μ—μ„œλ§Œ μ‘΄μž¬ν•˜λŠ” ν”„λ‘œνΌν‹° #if WITH_EDITORONLY_DATA UPROPERTY(EditAnywhere) UTexture2D* EditorPreviewTexture; // μΏ ν‚Ή μ‹œ 제거됨 β†’ λŸ°νƒ€μž„ GC λΆ€ν•˜ μ—†μŒ UPROPERTY(EditAnywhere) FString DeveloperNotes; #endif // λŸ°νƒ€μž„μ—λ„ μ‘΄μž¬ν•˜λŠ” ν”„λ‘œνΌν‹° UPROPERTY() UStaticMesh* GameMesh; }; // 에디터 μ „μš© λͺ¨λ“ˆμ˜ UObject // UEditorUtilityWidget, UEditorUtilityObject 등은 // μΏ ν‚Ή μ‹œ μ™„μ „νžˆ μ œκ±°λ˜μ–΄ λŸ°νƒ€μž„μ— 영ν–₯ μ—†μŒ
WITH_EDITORONLY_DATA의 GC 영ν–₯

WITH_EDITORONLY_DATA 블둝 λ‚΄μ˜ UPROPERTYλŠ” μΏ ν‚Ή(νŒ¨ν‚€μ§•) μ‹œ μ™„μ „νžˆ μ œκ±°λ©λ‹ˆλ‹€. μ΄λŠ” ν•΄λ‹Ή ν”„λ‘œνΌν‹°κ°€ GC 토큰 μŠ€νŠΈλ¦Όμ—λ„ ν¬ν•¨λ˜μ§€ μ•Šμ•„ λŸ°νƒ€μž„ GC μ„±λŠ₯에 영ν–₯을 μ£Όμ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 에디터 μ „μš© λ°μ΄ν„°λŠ” 이 블둝 μ•ˆμ— λ„£μœΌμ„Έμš”.

SECTION 04

에디터 λ©”λͺ¨λ¦¬ 관리 팁

λŒ€κ·œλͺ¨ ν”„λ‘œμ νŠΈμ—μ„œ 에디터 λ©”λͺ¨λ¦¬ 문제 ν•΄κ²°

에디터 λ©”λͺ¨λ¦¬ μ ˆμ•½ μ „λž΅

μ „λž΅ // 1. 에셋 λ ˆμ§€μŠ€νŠΈλ¦¬ μΊμ‹œ 관리 // μ½˜ν…μΈ  λΈŒλΌμš°μ €μ˜ λͺ¨λ“  에셋 = 메타데이터 λ‘œλ“œ // 폴더 ν•„ν„°λ₯Ό ν™œμš©ν•˜μ—¬ ν•„μš”ν•œ μ—μ…‹λ§Œ ν‘œμ‹œ // 2. μ—λ””ν„°μ—μ„œ κ°•μ œ GC // 파일 메뉴 β†’ "Collect Garbage" // λ˜λŠ” μ½˜μ†”: obj gc // 3. μ°Έμ‘° 정리 // μ½˜ν…μΈ  λΈŒλΌμš°μ € β†’ 에셋 우클릭 β†’ "Fix Up Redirectors" // 리디렉터가 에셋을 GCλ‘œλΆ€ν„° λ³΄ν˜Έν•˜λŠ” 경우 있음 // 4. 에디터 GC μ„€μ • μ‘°μ • gc.MaxObjectsInEditor=16777216 // 더 λ§Žμ€ 객체 ν—ˆμš© // 5. 에디터 μ „μš© 에셋 μ΅œμ†Œν™” // Developer ν΄λ”λŠ” μΏ ν‚Ή μ‹œ μ œμ™Έλ¨ // ν…ŒμŠ€νŠΈ 에셋은 Developer 폴더에 배치
SUMMARY

핡심 μš”μ•½

이 κ°•μ˜μ—μ„œ 배운 λ‚΄μš©
  • μ—λ””ν„°λŠ” λŸ°νƒ€μž„λ³΄λ‹€ UObject μˆ˜κ°€ 훨씬 많고 MaxObjects ν•œκ³„λ„ λ†’μŠ΅λ‹ˆλ‹€
  • PIE μ’…λ£Œ μ‹œ λŒ€λŸ‰ GCκ°€ λ°œμƒν•˜λ©°, 에디터 에셋 직접 μ°Έμ‘°λŠ” λ©”λͺ¨λ¦¬ λˆ„μˆ˜λ₯Ό μœ λ°œν•©λ‹ˆλ‹€
  • WITH_EDITORONLY_DATA의 ν”„λ‘œνΌν‹°λŠ” μΏ ν‚Ή μ‹œ GC 토큰 μŠ€νŠΈλ¦Όμ—μ„œ μ™„μ „νžˆ μ œκ±°λ©λ‹ˆλ‹€
  • TObjectPtrλŠ” μ—λ””ν„°μ—μ„œ μ§€μ—° λ‘œλ”©μ„, λŸ°νƒ€μž„μ—μ„œλŠ” raw 포인터 μ„±λŠ₯을 μ œκ³΅ν•©λ‹ˆλ‹€
  • ν…ŒμŠ€νŠΈ 에셋은 Developer 폴더에 λ°°μΉ˜ν•˜μ—¬ μΏ ν‚Ή μ‹œ μ œμ™Έν•©λ‹ˆλ‹€
PRACTICE

도전 과제

배운 λ‚΄μš©μ„ 직접 μ‹€μŠ΅ν•΄λ³΄μ„Έμš”

μ‹€μŠ΅ 1: 에디터/λŸ°νƒ€μž„ GC λ™μž‘ 차이 비ꡐ

에디터 PIE(Play In Editor)와 Standalone λΉŒλ“œμ—μ„œ λ™μΌν•œ GC ν…ŒμŠ€νŠΈ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜μ„Έμš”. gc.TimeBetweenPurgingPendingKillObjects, 에디터 μ „μš© Root 객체, RF_Standalone ν”Œλž˜κ·Έ λ“±μ˜ 차이λ₯Ό ν‘œλ‘œ μ •λ¦¬ν•˜μ„Έμš”.

μ‹€μŠ΅ 2: 에디터 Undo/Redo와 GC μƒν˜Έμž‘μš©

#if WITH_EDITOR λΈ”λ‘μ—μ„œ GEditor->GetTransaction()을 μ‚¬μš©ν•˜μ—¬ Undo νžˆμŠ€ν† λ¦¬κ°€ GC에 λ―ΈμΉ˜λŠ” 영ν–₯을 λΆ„μ„ν•˜μ„Έμš”. λŒ€λŸ‰μ˜ 에디터 μž‘μ—… ν›„ Undo νžˆμŠ€ν† λ¦¬μ˜ λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ„ memreport둜 ν™•μΈν•˜μ„Έμš”.

심화 과제: 에디터 μ „μš© GC μ΅œμ ν™” ν”ŒλŸ¬κ·ΈμΈ

μ—λ””ν„°μ—μ„œ μž‘μ—… μ‹œ GC 히치λ₯Ό 쀄이기 μœ„ν•œ 에디터 μœ ν‹Έλ¦¬ν‹° ν”ŒλŸ¬κ·ΈμΈμ„ κ°œλ°œν•˜μ„Έμš”. 에디터 유휴 μ‹œκ°„μ— GCλ₯Ό μ‹€ν–‰ν•˜λŠ” μŠ€μΌ€μ€„λŸ¬, 에디터 μ „μš© λ©”λͺ¨λ¦¬ 리포트, Undo νžˆμŠ€ν† λ¦¬ 정리 κΈ°λŠ₯을 ν¬ν•¨ν•˜μ„Έμš”.