Preprocessing data from a World Partition world

Hello, jumping in here after doing some testing. I was one of the people who mentioned WorldPartitionRuntimeCellTransformer to your team in the past. One thing I want to emphasize is that the WorldPartitionRuntimeCellTransformer are ran at cook-time so is a valid route for preprocessing worlds for cooked builds.

However, I’d like to update that recommendation since I understand a bit better what you’re trying to do and it would be convenient to be able to calculate that database at editor-time too without cooking a build. I think a World Partition Builder Commandlet is what you need for preprocessing the world. There are many examples in the engine where we use this to calculate data offline, including a commandlet that loads world partition cells one-by-one to generate navigation data for that cell.

UWorldPartitionNavigationDataBuilder and UWorldPartitionResaveActorsBuilder should be good reference to you. UWorldPartitionResaveActorsBuilder in particular demonstrates how to resave all actors with a commandlet and I think is a good template for you to do actor preprocessing instead (doesn’t have to resave or modify the actors then, but rather to export to your database). My suggestion for you is to create a custom UWorldPartitionBuilder class. You can then from commandline (outside of UnrealEditor) let that builder class run on an open world map and it gets to parse all actors in all cells. Here is an example:

`#pragma once

include “CoreMinimal.h”
include “WorldPartition/WorldPartitionBuilder.h”
include “MyWorldPartitionDatabaseBuilder.generated.h”

/**
*
*/
UCLASS()
class THIRDPERSON55R_API UMyWorldPartitionDatabaseBuilder : public UWorldPartitionBuilder
{
GENERATED_BODY()

public:
virtual bool RequiresCommandletRendering() const override;
virtual ELoadingMode GetLoadingMode() const override;
virtual bool PreRun(UWorld* World, FPackageSourceControlHelper& PackageHelper) override;
virtual bool RunInternal(UWorld* World, const FCellInfo& InCellInfo, FPackageSourceControlHelper& PackageHelper) override;
};``#include “MyWorldPartitionDatabaseBuilder.h”
include “WorldPartition/WorldPartition.h”
include “WorldPartition/WorldPartitionSubsystem.h”
include “EngineUtils.h”

bool UMyWorldPartitionDatabaseBuilder::RequiresCommandletRendering() const
{
return false;
}

UWorldPartitionBuilder::ELoadingMode UMyWorldPartitionDatabaseBuilder::GetLoadingMode() const
{
// Load cells one by one, calls RunInternal with world partially loaded multiple times
return ELoadingMode::IterativeCells2D;
}

bool UMyWorldPartitionDatabaseBuilder::PreRun(UWorld* World, FPackageSourceControlHelper& PackageHelper)
{
UE_LOG(LogTemp, Warning, TEXT(“Running UMyWorldPartitionDatabaseBuilder on world: %s”), *World->GetPathName());
return true;
}

bool UMyWorldPartitionDatabaseBuilder::RunInternal(UWorld* World, const FCellInfo& InCellInfo, FPackageSourceControlHelper& PackageHelper)
{
UE_LOG(LogTemp, Warning, TEXT(“RunInternal called on world: %s”), *World->GetPathName());
for (TActorIterator ItActor(World); ItActor; ++ItActor)
{
UE_LOG(LogTemp, Warning, TEXT(“STUB: Parse actor here - %s”), *ItActor->GetPathName());
}
return true;
}`

And running the commandlet:

"Z:/My/Path/Engine/Binaries/Win64/UnrealEditor.exe" "%cd%/ThirdPerson55R.uproject" "/Game/ThirdPerson/Maps/MAP_MyOpenWorld" -run=WorldPartitionBuilderCommandlet -SCCProvider=None -builder=MyWorldPartitionDatabaseBuilderThat should help you preprocess actors at least to extract any info you want and store in a custom database. You can detect here which actors have that component. Depending on what you return as GetLoadingMode(), you can have all actors loaded (memory heavy of course), or just actors in one cell at a time. If actors have soft object references to each other, then EntireWorld may be more appropriate if you want to have the other actor loaded too, but it might not be feasible depending on the size of your map so there is a pro and con. Please let us know if this brings you closer to what you need.

One thing to be aware of is that when running a WorldPartitionBuilder and getting the actor’s paths, all actors are loaded into the PersistentLevel. They may have a path like this:

/Game/ThirdPerson/Maps/MAP_MyOpenWorld.MAP_MyOpenWorld:PersistentLevel.StaticMeshActor_UAID_E04F43E60CEA876402_1193738857At runtime in PIE and in cooked builds they will have different paths. In PIE there will be a UEDPIE prefix, in cooked builds those actors will be loaded as part of a sublevel (a world partition cell) so not in the Persistent Level. Soft object reference properties of actors placed in the level will be fixed up so the paths work in PIE and in cooked builds, but if you copy actor paths into your custom database you will need to fix them up at runtime. I’ve asked a colleague to pitch in with what they know about that.

“The asset registry is more interesting.”

Regarding this idea, I’m not too familiar myself with using asset registry to find actors placed in the level. I believe that approach is more suitable to find blueprint assets and data assets, rather than one-file-per-actor actor assets.