수정 및 저장 처리(PIE에서도 동작)
// FSavePackageArgs 사용시 필요 헤더
#include "Windows/AllowWindowsPlatformTypes.h"
#include "windows.h" // any native windows header
#include "Windows/HideWindowsPlatformTypes.h"
#include "UObject/SavePackage.h"
// UEditorLoadingAndSavingUtils를 사용하여 저장시 필요한 헤더
#include "FileHelpers.h"
bool ChangeAndSaveTable()
{
FString filePath = TEXT("C:/Dev/Projects/TestProject/Content/Tables/NPCTable.uasset");
// 게임 베이스(/Game/Tables/NPCTable.uasset) 경로로 변경
FString gameBasePath = ConvertGameBasePath(filePath);
if (true == gameBasePath.IsEmpty()) {
return false;
}
// 대상 테이블로드를 위해 레퍼런스(/Game/Tables/NPCTable.NPCTable) 경로로 변경
FString fileName = FPaths::GetBaseFilename(gameBasePath);
gameBasePath = gameBasePath.Replace(TEXT("uasset"), *fileName);
// 테이블 로드
UDataTable* dataTable = Cast<UDataTable>(StaticLoadObject(UDataTable::StaticClass(), nullptr, *gameBasePath));
if (nullptr == dataTable) {
return false;
}
UPackage* package = dataTable->GetPackage();
if (nullptr == package) {
return false;
}
// 대상 테이블의 row 구조체가 처리할 구조체인지 체크
// 여기서는 FNPCTableRow 구조체
const UScriptStruct* rowStruct = dataTable->GetRowStruct();
if (nullptr == rowStruct || false == rowStruct->IsChildOf(FNPCTableRow::StaticStruct())) {
return false;
}
const TMap<FName, uint8*>& rowMap = dataTable->GetRowMap();
for (auto& pair : rowMap)
{
FNPCTableRow* row = (FNPCTableRow*)(&pair.Value[0]);
// 정보 수정
row->NPCName = TEXT("test");
}
FSavePackageArgs saveArgs;
saveArgs.TopLevelFlags = RF_Public | RF_Standalone;
saveArgs.Error = GWarn;
bool isSuccess = UPackage::SavePackage(package, dataTable, *filePath, saveArgs);
//isSuccess = UEditorLoadingAndSavingUtils::SavePackages({ package }, false); // 이것도 저장이 가능
return isSuccess;
}
1. 특정 경로(C:/Dev/Projects/TestProject/Content/Tables/NPCTable.uasset)의 DataTable의 정보( FNPCTableRow구조체)를 변경하고 저장
2-1. UPackage::SavePackage 사용
FSavePackageArgs를 사용하려면 SavePackage.h 헤더가 필요한데 추가시 에러가 발생하기 때문에
AllowWindowsPlatformTypes.h, windows.h, HideWindowsPlatformTypes.h 헤더도 추가가 필요하다
2-2. UEditorLoadingAndSavingUtils:: SavePackages 사용
FileHelpers.h 헤더가 필요하고, [프로젝트].Build.cs에 UnrealEd 모듈 추가가 필요(참고)
3. ConvertGameBasePath()는 상대/절대 경로를 /Game/ 기반의 경로로 변경하는 함수(참고)
데이터가 변경되고 아직 저장되지 않은 상태 표시(더티 플래그) 처리
bool ChangeAndMarkTable()
{
FString filePath = TEXT("C:/Dev/Projects/TestProject/Content/Tables/NPCTable.uasset");
// 게임 베이스(/Game/Tables/NPCTable.uasset) 경로로 변경
FString gameBasePath = ConvertGameBasePath(filePath);
if (true == gameBasePath.IsEmpty()) {
return false;
}
// 대상 테이블로드를 위해 레퍼런스(/Game/Tables/NPCTable.NPCTable) 경로로 변경
FString fileName = FPaths::GetBaseFilename(gameBasePath);
gameBasePath = gameBasePath.Replace(TEXT("uasset"), *fileName);
// 테이블 로드
UDataTable* dataTable = Cast<UDataTable>(StaticLoadObject(UDataTable::StaticClass(), nullptr, *gameBasePath));
if (nullptr == dataTable) {
return false;
}
UPackage* package = dataTable->GetPackage();
if (nullptr == package) {
return false;
}
// 대상 테이블의 row 구조체가 처리할 구조체인지 체크
const UScriptStruct* rowStruct = dataTable->GetRowStruct();
if (nullptr == rowStruct || false == rowStruct->IsChildOf(FNPCTableRow::StaticStruct())) {
return false;
}
const TMap<FName, uint8*>& rowMap = dataTable->GetRowMap();
for (auto& pair : rowMap)
{
FNPCTableRow* row = (FNPCTableRow*)(&pair.Value[0]);
// 정보 수정
row->NPCName = TEXT("test");
}
// 플래그 설정
bool isSuccess = dataTable->MarkPackageDirty();
return isSuccess;
}
PIE에서는 동작하지 않는데 MarkPackageDirty() 함수안에 보면 GIsPlayInEditorWorld가 true일 경우 처리되지 않게 되어있다
다음처럼 잠시 false로 만들어주면 처리는 된다
GIsPlayInEditorWorld = false;
dataTable->MarkPackageDirty();
GIsPlayInEditorWorld = true;
'Unreal > 기본' 카테고리의 다른 글
[Unreal] 경로 함수 (0) | 2025.01.12 |
---|---|
[Unreal] 프로젝트 기본 모듈 사용 (0) | 2025.01.11 |
[Unreal] 상대/절대 경로를 /Game/ 기반의 경로로 변경 (0) | 2025.01.05 |
[Unreal] 특정 디렉터리 파일 리스트 얻기 (0) | 2025.01.05 |
[Unreal] SoundCue에 설정된 SoundWave 리스트 얻기 (0) | 2024.11.30 |