x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Getting newly created assets from UObjectLibrary in commandlet

I am working on automating a process which creates a bunch of maps and spawns actors in sublevels via commandlet. I am currently having trouble getting a list of packages that have been newly created via UObjectLibrary.

Currently I am creating new world asset and registering it with the AssetRegistryModule using the following code:

 UWorld* FCustomImportCommandlet::CreateWorld(const FString& PackageName, const FString& LevelName)
 {
     UObject* WorldTemplate = StaticLoadObject(UWorld::StaticClass(), NULL, TEXT("World'/RNKImporter/Maps/TemplateMap.TemplateMap'"));
     ObjectTools::FPackageGroupName PGN;
     PGN.ObjectName =  ObjectTools::SanitizeObjectName(LevelName);
     PGN.PackageName = PackageTools::SanitizePackageName(PackageName);
     TSet<UPackage*> PackagesUserRefusedToFullyLoad;
     UWorld* World = CastChecked<UWorld>(ObjectTools::DuplicateSingleObject(WorldTemplate, PGN, PackagesUserRefusedToFullyLoad));
     FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(AssetRegistryConstants::ModuleName);
     AssetRegistryModule.Get().AssetCreated(World);
     World->InitializeNewWorld();
     return World;
 }

Then I save the packages to disk using a call to GEditor->SavePackage() for all dirty packages. I am then attempting to retrieve a list of the created levels using the following code:

 TArray<UWorld*> UCustomImporterLibrary::GetWorlds(const FString& Path)
 {
     TArray<UWorld*> Worlds;
     UObjectLibrary* ObjectLibrary = UObjectLibrary::CreateLibrary(UWorld::StaticClass(), false, true);
     ObjectLibrary->LoadAssetDataFromPath(Path);
     TArray<FAssetData> AssetData;
     ObjectLibrary->GetAssetDataList(AssetData);
     UE_LOG(LogTemp, Log, TEXT("Found: %d"), AssetData.Num());
 
     for (FAssetData Data : AssetData)
     {
         Worlds.Add(UWorld::FindWorldInPackage(Data.GetPackage()));
     }
     return Worlds;
 }

This works, returning the UWorld packages at the specified path, but only after the commandlet process has run to completion. If that function is called during the same run the ObjectLibrary is not populated and no packages are retrieved by ObjectLibrary->LoadAssetDataFromPath(Path).

In Summary:

If the above function is called during the same run the UWorld packages are created, no results are returned.

If the above function is called during a subsequent run the expected results are returned.

I am wondering if I am missing some step in the asset creation and registry process which would allow me to retrieve the packages via path using UObjectLibrary, or if there is a better way to create/retrieve packages for immediate use in a commandlet.

Product Version: UE 4.19
Tags:
more ▼

asked Apr 24 '18 at 12:40 AM in C++ Programming

avatar image

Clayton.Campbell
56 3 12 14

(comments are locked)
10|2000 characters needed characters left

1 answer: sort voted first

I have figured this out, the important was to set UObjectLibrary->bIncludeOnlyOnDiskAssets = false to get it to collect the newly created assets as well.

 TArray<UWorld*> UCustomImporterLibrary::GetWorlds(const FString& Path)
 {
     TArray<UWorld*> Worlds;
     // setup object library
     UObjectLibrary* ObjectLibrary = UObjectLibrary::CreateLibrary(UWorld::StaticClass(), false, false);
     ObjectLibrary->bIncludeOnlyOnDiskAssets = false;
     TArray<FString> Paths;
     Paths.Add(Path);
 
     // load asset data
     ObjectLibrary->LoadAssetDataFromPaths(Paths, true);
     TArray<FAssetData> AssetData;
     ObjectLibrary->GetAssetDataList(AssetData);
 
     // add assets to world list
     for (FAssetData Data : AssetData)
     {
         Worlds.Add(UWorld::FindWorldInPackage(Data.GetPackage()));
     }
     return Worlds;
 }

I have also changed to a slightly different method to create the levels; Using UWorldFactory to generate the world.

 UWorld* FCustomImportCommandlet::CreateWorld(const FString& PackageName, const FString& LevelName)
 {
     // Create a new world
     UWorldFactory* Factory = NewObject<UWorldFactory>();
     Factory->WorldType = EWorldType::Editor;
     Factory->bInformEngineOfWorld = true;
     Factory->FeatureLevel = GEditor->DefaultWorldFeatureLevel;
     EObjectFlags Flags = RF_Public | RF_Standalone;
     FString SanitizedPackageName = PackageTools::SanitizePackageName(PackageName);
     FPaths::RemoveDuplicateSlashes(SanitizedPackageName);
     UPackage* Pkg = CreatePackage(NULL, *SanitizedPackageName);
     Pkg->AddToRoot();
     UWorld* NewWorld = CastChecked<UWorld>(Factory->FactoryCreateNew(UWorld::StaticClass(), Pkg, FName(*LevelName), Flags, NULL, GWarn));
     NewWorld->UpdateWorldComponents(true, true);
     NewWorld->AddToRoot();
     NewWorld->MarkPackageDirty();
     FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(AssetRegistryConstants::ModuleName);
     AssetRegistryModule.Get().AssetCreated(NewWorld);
     return NewWorld;
 }
more ▼

answered Apr 25 '18 at 05:10 PM

avatar image

Clayton.Campbell
56 3 12 14

(comments are locked)
10|2000 characters needed characters left
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question