# Asset Export to JSON - 언리얼 엔진 에디터 확장 기능 ## 개요 본 에디터 확장 기능은 언리얼 엔진 에셋을 JSON 형식으로 변환하여 LLM 기반 전투 밸런스 분석을 수행할 수 있는 포괄적인 에셋 익스포트 시스템을 제공합니다. 다양한 에셋 타입에서 상세한 데이터를 추출하여 AI 시스템이 분석할 수 있는 텍스트 기반 문서를 생성합니다. **목적**: 대규모 언어 모델(LLM) 처리에 적합한 구조화된 텍스트 기반 게임 에셋 표현을 제공하여 포괄적인 전투 밸런스 분석을 가능하게 합니다. **지원 에셋 타입**: - **DataTable** - 완전한 행/열 데이터 - **Blueprint** - 변수, 함수, 컴포넌트, 노드 연결을 포함한 이벤트 그래프 - **AnimMontage** - 섹션, 노티파이, 커스텀 프로퍼티, 슬롯 애니메이션 - **CurveTable** - 키-값 커브 데이터 (RichCurves 및 SimpleCurves) ## 주요 기능 ### 설정 기반 익스포트 - **프로젝트 설정 통합**: `편집 → 프로젝트 설정 → 플러그인 → Asset Export to JSON`에서 익스포트 경로 설정 - **영구 설정**: 설정이 `Config/DefaultEditor.ini`에 저장되어 SVN/Git을 통한 팀 공유 가능 - **다중 폴더 지원**: 한 번의 클릭으로 여러 폴더 경로에서 익스포트 - **에셋 타입 필터링**: 설정을 통해 특정 에셋 타입 활성화/비활성화 ### 두 가지 익스포트 방식 #### 1. 대량 익스포트 (Tools 메뉴) - 설정된 모든 폴더의 에셋을 한 번에 익스포트 - 프로젝트 전체 밸런스 분석에 적합 - `Tools → WorldStalker → Export Assets to JSON` #### 2. 단일 에셋 익스포트 (우클릭 메뉴) - Content Browser에서 개별 에셋 우클릭 후 즉시 익스포트 - 빠른 테스트 및 반복 작업에 적합 - 타임스탬프 파일명 자동 생성 ### 포괄적인 데이터 추출 #### Blueprint 익스포트 **변수 추출 - 3가지 소스**: 1. **Blueprint 커스텀 변수** (`Blueprint->NewVariables`) - Blueprint 에디터에서 추가한 모든 커스텀 변수 - 변수 GUID, 타입 정보 (Category, SubCategory, ContainerType) - Property flags (IsEditable, IsBlueprintVisible, IsExposedOnSpawn 등) - 카테고리명 및 전체 메타데이터 - Replication 설정 2. **C++ 부모 클래스 프로퍼티** (`Category = "WorldStalker"`) - ✨ **NEW**: C++ 부모 클래스에서 정의된 중요 프로퍼티 추출 - **ActivationOrderGroup** - 스킬 실행 순서 그룹 - **bDisableOrderGroup** - 순서 그룹 비활성화 여부 - **bCanBeCancel** - 취소 가능 여부 - **ActivationTrigger** - 발동 트리거 타입 - **bStopAutoTargetWhenEndAbility** - 어빌리티 종료 시 자동 타겟 중지 - Source 필드로 "C++ParentClass" 표시 - OwnerClass 필드로 정의된 C++ 클래스 명시 3. **컴파일된 클래스 프로퍼티** - 부모 클래스에서 상속된 기타 프로퍼티 **함수**: - 입력/출력 파라미터를 포함한 함수 목록 - FunctionGraphs에서 추출 **컴포넌트**: - 컴포넌트 계층 구조 - SimpleConstructionScript에서 추출 **이벤트 그래프**: 다음을 포함한 완전한 노드 그래프 - 노드 타입, 제목, 위치, 코멘트 - 핀 타입, 방향, 기본값 - 핀 간 연결 그래프 - 노드별 프로퍼티 #### AnimMontage 익스포트 - 시작/종료 시간을 포함한 섹션 - 세그먼트를 포함한 슬롯 애니메이션 트랙 - **노티파이 이벤트**: 다음을 포함한 완전한 노티파이 데이터 - 노티파이 타입 및 트리거 시간 - 노티파이 클래스의 커스텀 프로퍼티 - 블렌드 인/아웃 설정 - 트랙 인덱스 및 싱크 마커 #### CurveTable 익스포트 - RichCurves와 SimpleCurves 모두 지원 - 시간, 값, 탄젠트 정보를 포함한 키 데이터 - 커브 보간 모드 ### 진행 상황 로깅 - ✨ **NEW**: 10개 에셋마다 진행 상황 로그 출력 - Output Log에서 실시간 진행 상황 확인 가능 - 에디터가 먹통처럼 보이는 현상 방지 - 로그 카테고리: `LogAssetExporter` ### 출력 관리 - **타임스탬프 익스포트**: 익스포트 히스토리 보관을 위한 선택적 타임스탬프 하위 폴더 - **타입별 파일 분리**: 에셋 타입별 개별 JSON 파일 (DataTable.json, Blueprint.json 등) - **보기 좋은 JSON 형식**: 들여쓰기가 적용된 사람이 읽기 쉬운 형식 - **중복 검출**: 폴더가 겹칠 때 중복 익스포트 방지 ## 설치 방법 ### 1. 파일 구조 다음 파일들을 프로젝트에 복사하세요: **새 파일** (`Source/WorldStalkerEditor/Utility/`에 복사): ``` AssetExportSettings.h AssetExportSettings.cpp AssetExporterToJSON.h AssetExporterToJSON.cpp ``` **수정된 파일** (수동으로 변경사항 병합): - `WorldStalkerEditor.h` - MERGE_INSTRUCTIONS.md 참조 - `WorldStalkerEditor.cpp` - MERGE_INSTRUCTIONS.md 참조 ### 2. 빌드 설정 `WorldStalkerEditor.Build.cs`에 다음을 추가하세요: ```csharp PublicDependencyModuleNames.AddRange(new string[] { "AssetRegistry", "Json", "JsonUtilities" }); PrivateDependencyModuleNames.AddRange(new string[] { "UnrealEd", "Engine", "Slate", "SlateCore", "ToolMenus", "DeveloperSettings", "ContentBrowser" // 우클릭 메뉴용 }); ``` ### 3. 프로젝트 리빌드 ```batch # Visual Studio 프로젝트 파일 생성 GenerateVSProjectFile.bat # 에디터 모듈 빌드 # 또는 Visual Studio에서 리빌드 ``` ## 설정 방법 ### 1단계: 프로젝트 설정 열기 다음으로 이동: `편집 → 프로젝트 설정 → 플러그인 → Asset Export to JSON` ### 2단계: 익스포트 경로 설정 **Export Folder Paths** (배열): - `/Game/` 콘텐츠 디렉토리 기준 상대 경로로 폴더 경로 추가 - 예시 경로: - `Blueprints/Enemy` - `Blueprints/Characters` - `Blueprints/Abilities` - `DataTables` - `+` 버튼으로 새 경로 추가 - `-` 버튼으로 경로 제거 **기본 경로** (자동 설정됨): ``` Blueprints/Enemy Blueprints/Characters Blueprints/Abilities DataTables ``` ### 3단계: 출력 설정 구성 **Output Directory** (출력 디렉토리): - 기본값: `Exports` (Content 폴더 기준 상대 경로) - 원하는 경우 커스텀 경로 설정 **Create Timestamped Folder** (타임스탬프 폴더 생성): - 활성화: `Export_2025_01_15_143022`와 같은 하위 폴더 생성 - 비활성화: 출력 디렉토리의 파일을 덮어씀 ### 4단계: 에셋 타입 선택 특정 에셋 타입에 대한 익스포트 활성화 또는 비활성화: - ☑ Export DataTables (데이터테이블 익스포트) - ☑ Export Blueprints (블루프린트 익스포트) - ☑ Export AnimMontages (애님 몽타주 익스포트) - ☑ Export CurveTables (커브테이블 익스포트) ## 사용 방법 ### 방법 1: 대량 익스포트 (Tools 메뉴) **전체 프로젝트 밸런스 분석용** 1. 언리얼 에디터 열기 2. 다음으로 이동: `Tools → WorldStalker → Export Assets to JSON` 3. Output Log에서 진행 상황 확인 (`Window → Developer Tools → Output Log`) - 로그 필터: `LogAssetExporter` 4. 익스포트 완료 대기 (알림 대화상자가 표시됨) **Output Log 예시**: ``` LogAssetExporter: Starting Asset Export to JSON process... LogAssetExporter: Export path: /Game/Blueprints/Abilities LogAssetExporter: Found 45 Blueprints to export LogAssetExporter: Processing Blueprint 1/45: GA_Skill_Cazimord_Flash LogAssetExporter: Processing Blueprint 10/45: GA_Skill_Fireball LogAssetExporter: Processing Blueprint 20/45: GA_Skill_IceSpear ... LogAssetExporter: Exported 45 Blueprints LogAssetExporter: Export completed! Total assets exported: 168 ``` ### 방법 2: 단일 에셋 익스포트 (우클릭) **빠른 테스트 및 반복 작업용** 1. Content Browser에서 익스포트할 에셋 찾기 2. 에셋 우클릭 3. **"Export to JSON"** 선택 4. 즉시 익스포트 완료 (확인 대화상자 표시) **지원 에셋 타입**: - DataTable - Blueprint - AnimMontage - CurveTable **출력 파일명 형식**: ``` Blueprint_GA_Skill_Cazimord_Flash_20251023_143205.json AnimMontage_AM_Attack_Combo_20251023_143210.json ``` ### 익스포트 출력 파일이 저장되는 위치: `Content/Exports/` (또는 설정된 출력 디렉토리) **출력 구조** (타임스탬프 폴더 사용 시): ``` Content/ └── Exports/ └── Export_2025_01_15_143022/ ├── DataTable.json ├── Blueprint.json ├── AnimMontage.json └── CurveTable.json ``` ### 출력 형식 예시 #### DataTable.json ```json { "ExportedAt": "2025-10-23 14:32:05", "TotalCount": 10, "Assets": [ { "AssetName": "DT_CharacterStats", "AssetPath": "/Game/DataTables/DT_CharacterStats", "RowStructure": "FCharacterStats", "Rows": [ { "RowName": "Warrior", "Data": { "Name": "Warrior", "Health": 1000.0, "Attack": 150.0, "Defense": 100.0 } } ] } ] } ``` #### Blueprint.json - 변수 섹션 ```json { "AssetName": "GA_Skill_Cazimord_Flash", "AssetPath": "/Game/Blueprints/Abilities/GA_Skill_Cazimord_Flash", "ParentClass": "WSGameplayAbility", "Variables": [ { "Name": "ActivationOrderGroup", "Type": "uint8", "DefaultValue": "1", "CategoryName": "WorldStalker", "Source": "C++ParentClass", "OwnerClass": "WSGameplayAbility", "IsEditable": true, "IsBlueprintVisible": true, "IsBlueprintReadOnly": false, "IsEditDefaultsOnly": true }, { "Name": "bDisableOrderGroup", "Type": "bool", "DefaultValue": "False", "CategoryName": "WorldStalker", "Source": "C++ParentClass", "OwnerClass": "WSGameplayAbility" }, { "Name": "CustomDamageMultiplier", "VarGuid": "A1B2C3D4-E5F6-7890-ABCD-EF1234567890", "Category": "float", "DefaultValue": "1.5", "Source": "Blueprint", "IsEditable": true, "IsBlueprintVisible": true, "CategoryName": "Combat", "MetaData": { "DisplayName": "데미지 배율", "Tooltip": "스킬 데미지 최종 배율" } } ], "Functions": [...], "Components": [...], "EventGraphs": [...] } ``` **변수 Source 타입 설명**: - `"Blueprint"`: Blueprint 에디터에서 추가한 커스텀 변수 - `"C++ParentClass"`: C++ 부모 클래스에서 정의된 프로퍼티 (Category = "WorldStalker") - `"CompiledClass"`: 기타 컴파일된 클래스 프로퍼티 #### AnimMontage.json ```json { "AssetName": "AM_Attack_Combo", "AssetPath": "/Game/Animations/AM_Attack_Combo", "SequenceLength": 2.5, "RateScale": 1.0, "Sections": [ { "SectionName": "Combo1", "StartTime": 0.0, "NextSectionName": "Combo2" } ], "AnimNotifies": [ { "NotifyName": "DealDamage", "TriggerTime": 0.5, "Duration": 0.0, "NotifyType": "Notify", "NotifyClass": "ANS_DealDamage", "CustomProperties": { "DamageAmount": "50.0", "DamageType": "Physical" } } ], "SlotAnimTracks": [ { "SlotName": "DefaultSlot", "AnimSegments": [ { "AnimReference": "AS_Attack1", "AnimPath": "/Game/Animation/Sequences/AS_Attack1", "StartPos": 0.0, "AnimStartTime": 0.0, "AnimEndTime": 1.0, "AnimPlayRate": 1.0, "LoopingCount": 1 } ] } ], "BlendInTime": 0.25, "BlendOutTime": 0.25, "BlendModeIn": "Standard", "BlendModeOut": "Standard" } ``` ## 전투 밸런스 분석 활용 예시 ### 워크플로우 1. **전체 스킬 익스포트** ``` Project Settings → Asset Export to JSON Export Folder Paths에 "/Game/Blueprints/Abilities" 추가 Tools → Export Assets to JSON 실행 ``` 2. **익스포트된 JSON 분석** ```python import json with open('Content/Exports/Blueprint.json', encoding='utf-8') as f: data = json.load(f) # ActivationOrderGroup 분석 for asset in data['Assets']: if 'GA_Skill' in asset['AssetName']: variables = asset['Variables'] # C++ 부모 클래스 프로퍼티 찾기 for var in variables: if var['Source'] == 'C++ParentClass': if var['Name'] == 'ActivationOrderGroup': print(f"{asset['AssetName']}: Order Group = {var['DefaultValue']}") ``` 3. **특정 스킬 수정 후 빠른 재분석** ``` 1. GA_Skill_Cazimord_Flash 블루프린트 수정 2. Content Browser에서 우클릭 → Export to JSON 3. 생성된 단일 JSON 파일로 LLM 분석 4. 밸런스 피드백 받기 5. 반복 ``` ### LLM 프롬프트 예시 ``` 다음 스킬 Blueprint JSON을 분석해주세요: [JSON 데이터 붙여넣기] 분석 포인트: 1. ActivationOrderGroup 값이 적절한가? 2. 같은 그룹의 다른 스킬들과 밸런스가 맞는가? 3. CustomProperties의 데미지 배율이 적정한가? 4. AnimMontage의 타이밍과 DealDamage 노티파이 시점이 일치하는가? ``` ## 문제 해결 ### 출력 파일이 생성되지 않음 **문제**: 익스포트가 완료되었지만 JSON 파일이 생성되지 않음 **해결**: 익스포트 경로에 활성화된 타입의 에셋이 포함되어 있는지 확인 ### 우클릭 메뉴가 나타나지 않음 **문제**: Content Browser에서 에셋 우클릭 시 "Export to JSON" 메뉴가 없음 **해결**: - 지원되는 에셋 타입인지 확인 (DataTable, Blueprint, AnimMontage, CurveTable) - 단일 에셋만 선택했는지 확인 (다중 선택 시 메뉴 비활성화) - 에디터 재시작 시도 ### C++ 프로퍼티가 익스포트되지 않음 **문제**: ActivationOrderGroup 같은 C++ 프로퍼티가 JSON에 없음 **해결**: - Property에 `Category = "WorldStalker"` 메타데이터가 있는지 확인 - C++ 헤더 파일에서 `UPROPERTY(EditDefaultsOnly, Category = "WorldStalker")` 선언 확인 - 최신 코드로 빌드되었는지 확인 ### 출력에 중복 에셋 **문제**: 동일한 에셋이 JSON에 여러 번 나타남 **해결**: 이제 중복 검출로 방지됨 - 설정에서 겹치는 폴더 경로 확인 ### 진행 상황이 보이지 않음 **문제**: 익스포트 중 에디터가 먹통처럼 보임 **해결**: Output Log 열기 (`Window → Developer Tools → Output Log`) - 필터에 `LogAssetExporter` 입력 - 10개 에셋마다 진행 상황 로그 확인 가능 ### 통합 후 빌드 오류 **문제**: 누락된 헤더에 대한 컴파일 오류 **해결**: 모든 의존성이 `.Build.cs` 파일에 추가되었는지 확인 (설치 섹션 참조) ### 대형 프로젝트에서 익스포트 중단 **문제**: 익스포트가 매우 오래 걸림 **해결**: 익스포트 경로 수를 줄이거나 필요하지 않은 에셋 타입 비활성화 ### 설정이 유지되지 않음 **문제**: 에디터 재시작 후 설정 초기화 **해결**: `Config/DefaultEditor.ini`가 쓰기 가능하고 잠겨있지 않은지 확인 ## 기술 세부사항 ### 언리얼 엔진 버전 - **테스트 환경**: 언리얼 엔진 5.5.4 (커스텀 빌드) - **API 호환성**: UE 5.5+ CurveTable API 사용 (GetRichCurveRowMap/GetSimpleCurveRowMap) ### 모듈 의존성 - **AssetRegistry** - 에셋 검색 및 필터링 - **Json/JsonUtilities** - JSON 직렬화 - **UnrealEd** - 에디터 통합 - **ToolMenus** - 메뉴 확장 시스템 - **DeveloperSettings** - 프로젝트 설정 통합 - **ContentBrowser** - 우클릭 컨텍스트 메뉴 ### 성능 특성 - **재귀 검색**: 설정된 경로의 모든 하위 폴더 검색 - **메모리 사용량**: 메모리 사용량을 최소화하기 위해 에셋을 하나씩 로드 - **익스포트 속도**: 에셋 복잡도에 따라 초당 약 10-50개 에셋 - **진행 상황**: 10개 에셋마다 로그 출력으로 진행 상황 실시간 확인 ### Blueprint 변수 추출 상세 시스템은 3가지 소스에서 변수를 추출합니다: **1. Blueprint 커스텀 변수 (`Blueprint->NewVariables`)** ```cpp for (const FBPVariableDescription& Variable : Blueprint->NewVariables) { // VarName, VarGuid, VarType, DefaultValue 추출 // PropertyFlags, Category, MetaData 추출 } ``` **2. C++ 부모 클래스 프로퍼티 (Category = "WorldStalker")** ```cpp for (TFieldIterator PropIt(Blueprint->GeneratedClass); PropIt; ++PropIt) { const FString* CategoryMeta = PropIt->FindMetaData(TEXT("Category")); if (CategoryMeta && CategoryMeta->Equals(TEXT("WorldStalker"))) { // ActivationOrderGroup 등 중요 프로퍼티 추출 } } ``` **3. 기타 컴파일된 클래스 프로퍼티** - 부모 클래스에서 상속된 기타 프로퍼티 ### Blueprint 이벤트 그래프 추출 시스템은 Blueprint 그래프 구조를 순회하여 다음을 추출합니다: - `UbergraphPages`의 모든 노드 (이벤트 그래프) - 노드 메타데이터 (클래스, 제목, 위치, 코멘트) - 핀 정보 (타입, 방향, 기본값) - 핀 간 연결 그래프 (LinkedTo 관계) - 그래프 노드의 프로퍼티 값 ### AnimMontage 커스텀 프로퍼티 추출 커스텀 프로퍼티는 다음 방식으로 Notify 객체에서 추출됩니다: 1. 모든 `AnimNotifyEvent` 항목 반복 2. Notify 객체 클래스 프로퍼티 리플렉션 3. 편집 가능한 프로퍼티 필터링 (`CPF_Edit` 플래그) 4. 프로퍼티 값을 JSON으로 직렬화 ## 알려진 제한사항 1. **Blueprint 비주얼 스크립트 로직**: 노드 그래프 구조는 익스포트하지만 비주얼 스크립트 바이트코드 실행 흐름은 익스포트하지 않음 2. **바이너리 에셋**: 바이너리 데이터 (메시, 텍스처, 오디오)는 익스포트할 수 없음 3. **복잡한 프로퍼티 타입**: 일부 복잡한 UObject 프로퍼티는 객체 참조로만 익스포트될 수 있음 4. **대형 Blueprint**: 수천 개의 노드가 있는 매우 큰 블루프린트는 익스포트에 상당한 시간이 걸릴 수 있음 5. **카테고리 필터**: 현재 "WorldStalker" 카테고리만 C++ 프로퍼티를 추출 (필요시 코드 수정으로 다른 카테고리 추가 가능) ## 개발 히스토리 ### Version 1.0 (2025-10-23) **초기 릴리스**: 포괄적인 에셋 추출 기능을 갖춘 INI 기반 설정 시스템 **주요 기능**: - ✅ Blueprint 커스텀 변수 (NewVariables) 완전 추출 - ✅ C++ 부모 클래스 프로퍼티 추출 (Category = "WorldStalker") - ActivationOrderGroup 등 중요 프로퍼티 지원 - ✅ 우클릭 컨텍스트 메뉴로 단일 에셋 빠른 익스포트 - ✅ 진행 상황 로깅 (10개 에셋마다) - ✅ AnimMontage 커스텀 프로퍼티 추출 - ✅ 이벤트 그래프 노드 연결 추출 - ✅ INI 기반 영구 설정 **주요 설계 결정**: - 반복 사용의 편의성을 위해 체크박스 UI 대신 INI 기반 설정 선택 - 버전 관리를 통한 팀 협업을 위한 UDeveloperSettings 통합 - 겹치는 폴더 경로로부터 중복 익스포트 방지를 위한 중복 검출 - 사람의 가독성과 LLM 처리를 위한 보기 좋은 JSON 형식 - C++ 부모 클래스 프로퍼티 추출로 스킬 밸런스 분석 강화 ## 지원 이슈, 질문 또는 기능 요청: 1. 본 README 및 MERGE_INSTRUCTIONS.md 확인 2. 언리얼 에디터의 출력 로그에서 오류 메시지 검토 3. 연락처: jinilkim@oneunivrs.com ## 라이선스 Copyright Epic Games, Inc. All Rights Reserved. WorldStalker (DungeonStalkers) 프로젝트의 일부입니다.