Add single asset export functionality and enhance README with usage details

This commit is contained in:
2025-10-23 21:02:50 +09:00
parent e988c90e2e
commit 4671fcc0bb
3 changed files with 674 additions and 88 deletions

415
README.md
View File

@ -20,17 +20,57 @@
- **다중 폴더 지원**: 한 번의 클릭으로 여러 폴더 경로에서 익스포트
- **에셋 타입 필터링**: 설정을 통해 특정 에셋 타입 활성화/비활성화
### 두 가지 익스포트 방식
#### 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 익스포트
- 시작/종료 시간을 포함한 섹션
@ -46,6 +86,12 @@
- 시간, 값, 탄젠트 정보를 포함한 키 데이터
- 커브 보간 모드
### 진행 상황 로깅
-**NEW**: 10개 에셋마다 진행 상황 로그 출력
- Output Log에서 실시간 진행 상황 확인 가능
- 에디터가 먹통처럼 보이는 현상 방지
- 로그 카테고리: `LogAssetExporter`
### 출력 관리
- **타임스탬프 익스포트**: 익스포트 히스토리 보관을 위한 선택적 타임스탬프 하위 폴더
- **타입별 파일 분리**: 에셋 타입별 개별 JSON 파일 (DataTable.json, Blueprint.json 등)
@ -87,7 +133,8 @@ PrivateDependencyModuleNames.AddRange(new string[] {
"Slate",
"SlateCore",
"ToolMenus",
"DeveloperSettings"
"DeveloperSettings",
"ContentBrowser" // 우클릭 메뉴용
});
```
@ -147,11 +194,49 @@ DataTables
## 사용 방법
### 빠른 익스포트
### 방법 1: 대량 익스포트 (Tools 메뉴)
**전체 프로젝트 밸런스 분석용**
1. 언리얼 에디터 열기
2. 다음으로 이동: ` → WorldStalker → Export Assets to JSON`
3. 익스포트 완료 대기 (알림 대화상자가 표시됨)
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
```
### 익스포트 출력
@ -172,90 +257,185 @@ Content/
#### DataTable.json
```json
[
{
"AssetName": "DT_CharacterStats",
"AssetPath": "/Game/DataTables/DT_CharacterStats",
"RowCount": 10,
"Columns": ["Name", "Health", "Attack", "Defense"],
"Rows": {
"Warrior": {
"Name": "Warrior",
"Health": "1000",
"Attack": "150",
"Defense": "100"
}
{
"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
#### Blueprint.json - 변수 섹션
```json
[
{
"AssetName": "BP_Enemy_Goblin",
"AssetPath": "/Game/Blueprints/Enemy/BP_Enemy_Goblin",
"ParentClass": "WSCharacterBase",
"Variables": [
{
"Name": "MaxHealth",
"Type": "float",
"DefaultValue": "500.0"
{
"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": "스킬 데미지 최종 배율"
}
],
"EventGraphs": [
{
"GraphName": "EventGraph",
"Nodes": [
{
"NodeTitle": "Event BeginPlay",
"NodeClass": "K2Node_Event",
"Pins": [...]
}
],
"Connections": [
{
"SourceNode": "Event BeginPlay",
"SourcePin": "then",
"TargetNode": "Set Max Health",
"TargetPin": "execute"
}
]
}
]
}
]
}
],
"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,
"Sections": [
{
"SectionName": "Combo1",
"StartTime": 0.0,
"EndTime": 0.8
{
"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"
}
],
"Notifies": [
{
"NotifyName": "DamageNotify",
"TriggerTime": 0.5,
"NotifyType": "AnimNotify",
"CustomProperties": {
"DamageMultiplier": "1.5",
"HitboxSize": "100.0"
}
],
"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
}
}
],
"SlotAnimTracks": [...]
}
]
]
}
],
"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 노티파이 시점이 일치하는가?
```
## 문제 해결
@ -265,11 +445,34 @@ Content/
**문제**: 익스포트가 완료되었지만 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개 에셋마다 진행 상황 로그 확인 가능
### 통합 후 빌드 오류
**문제**: 누락된 헤더에 대한 컴파일 오류
@ -297,11 +500,41 @@ Content/
- **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<FProperty> PropIt(Blueprint->GeneratedClass); PropIt; ++PropIt)
{
const FString* CategoryMeta = PropIt->FindMetaData(TEXT("Category"));
if (CategoryMeta && CategoryMeta->Equals(TEXT("WorldStalker")))
{
// ActivationOrderGroup 등 중요 프로퍼티 추출
}
}
```
**3. 기타 컴파일된 클래스 프로퍼티**
- 부모 클래스에서 상속된 기타 프로퍼티
### Blueprint 이벤트 그래프 추출
시스템은 Blueprint 그래프 구조를 순회하여 다음을 추출합니다:
@ -324,16 +557,30 @@ Content/
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++ 부모 클래스 프로퍼티 추출로 스킬 밸런스 분석 강화
## 지원