I am trying to write a commandlet that creates an empty map, spawns a list of Static Mesh Actors into it and saves it.
I would also like to access the map from the editor for debug purposes.
I have tried multiple approaches, both by taking inspiration from the C++ APIs and from other projects (e.g. CARLA sim), however due to the lack of documentation on this specific feature it’s been very hard.
The two approaches I tried to follow are:
- Use the function
UEditorLoadingAndSavingUtils::NewBlankMap(bool);
and thenUEditorLoadingAndSavingUtils::SaveMap( UWorld * World, const FString & AssetPath)
, which either generates crashes during the procedure or does not generate a map file at all - Create an empty map in the contents folder (let’s call it
BaseMap
), use that as a base, then useUPackage
andFAssetRegistryModule
to create a new instance in another folder, then save it usingUPackage::SavePackage
. This creates a new map (let’s call thisFinalMap
), but it’s as if this new map was a “link” toBaseMap
(if I modifyBaseMap
, save it and then openFinalMap
, the latter will have the changes ofBaseMap
).
This is the code that I used for the second approach:
TArray<AStaticMeshActor*> UExportAssetsForPackagingCommandlet::GenerateNewMap(
const TArray<FString>& AssetsPaths, const FString& MapPath)
{
UWorld* ExporterWorld = CastChecked<UWorld>(ExporterMapData.GetAsset());
UPackage* ExporterPackage = ExporterMapData.GetPackage();
FString OutputFolder(TEXT("/Game/Exporter/Output"));
ExporterPackage->SetFolderName(*OutputFolder);
ExporterPackage->FullyLoad();
ExporterPackage->MarkPackageDirty();
FAssetRegistryModule::AssetCreated(ExporterWorld);
ExporterWorld->Rename(TEXT("Assets_To_Export"), ExporterWorld->GetOuter());
FString PackagePath = OutputFolder + TEXT("/AssetsExporter");
FAssetRegistryModule::AssetRenamed(ExporterPackage, *PackagePath);
ExporterPackage->MarkPackageDirty();
FString PackageFileName = FPackageName::LongPackageNameToFilename(PackagePath, FPackageName::GetMapPackageExtension());
UPackage::SavePackage(ExporterPackage, ExporterWorld, EObjectFlags::RF_Public | EObjectFlags::RF_Standalone, *PackageFileName,
GError, nullptr, true, true, SAVE_NoError);
return {}; // SpawnedMeshes;
}
Is there a correct way of doing this? Where can I find the documentation for procedurally create a map file from scratch in C++?
If it was possible I would also like to understand what’s the concept of packages and how it relates to assets because the official documentation only talks about packages when talking about “Packaging a game”, but it seems to be a different concept when talking about assets handling.