Hi!
At our project we are testing commandlets for nav data generation and manipulation.
We have a World Partition level and we use the commandlet to build the nav
"/Game/Developers/BrunoPistoni/Levels/WPTest_NavGen.umap" -run=WorldPartitionBuilderCommandlet -AllowCommandletRendering -builder=HexWorldPartitionNavigationDataBuilder -SCCProvider=None
In this case, HexWorldPartitionNavigationDataBuilder is our custom navigation data builder.
In it, we override PostRun with the idea of post-process the generated nav data to clean it out.
The way we do it is the following
// load the world (temp hack, propper cell-by-cell logic will be used)
const FBox BoxEntireWorld = FBox(FVector(-HALF_WORLD_MAX, -HALF_WORLD_MAX, -HALF_WORLD_MAX), FVector(HALF_WORLD_MAX, HALF_WORLD_MAX, HALF_WORLD_MAX));
TUniquePtr<FLoaderAdapterShape> LoaderAdapterShape = MakeUnique<FLoaderAdapterShape>(World, BoxEntireWorld, TEXT("Loaded Region"));
LoaderAdapterShape->Load();
// load every FHexNavFloodTask to start the nav flooding process
for (TActorIterator<AHexNavFloodReference> It(World); It; ++It)
{
UPackage* Pkg = It->GetPackage();
if (Pkg)
{
LoadPackage(nullptr, *SourceControlHelpers::PackageFilename(Pkg), LOAD_None);
}
}
// look for every NavigationDataChunk in the world
TArray<FString> PackageFiles;
for (TActorIterator<ANavigationDataChunkActor> It(World); It; ++It)
{
UPackage* Pkg = It->GetPackage();
if (Pkg)
{
PackageFiles.AddUnique(SourceControlHelpers::PackageFilename(Pkg));
}
}
// load each NavDataChunkActor
for (const FString& PackageFile : PackageFiles)
{
FString LongPackageName;
if (!FPackageName::TryConvertFilenameToLongPackageName(PackageFile, LongPackageName))
{
continue;
}
UPackage* LoadedPackage = LoadPackage(nullptr, *LongPackageName, LOAD_None);
if (!LoadedPackage)
{
continue;
}
// Find the ANavigationDataChunkActor inside the package (if present)
for (TObjectIterator<ANavigationDataChunkActor> ChunkIt; ChunkIt; ++ChunkIt)
{
if (ChunkIt->GetPackage() == LoadedPackage)
{
ANavigationDataChunkActor* ChunkActor = *ChunkIt;
AHexRecastNavMesh* Recast = FindRecastNavMeshForChunk(ChunkActor); // we only use one nav data, so Recast is always the same object
if (Recast)
{
TObjectPtr<UHexNavFlooder> navFlooder = NewObject<UHexNavFlooder>(GetTransientPackage(), TEXT("navFlooder"));
if (::IsValid(navFlooder))
{
//[do all our cleaning nav process, no need to show this code] navFlooder->FloodNav();
// update the actor navData (is this needed?)
FBox tileBounds(EForceInit::ForceInit);
ChunkActor->CollectNavData(ChunkActor->GetBounds(), tileBounds);
// Mark the package dirty so saving will persist changes
LoadedPackage->SetDirtyFlag(true);
Recast->GetPackage()->SetDirtyFlag(true);
}
}
}
}
// find the packages we need to save and save them
for (UPackage* Pkg : PackagesToSave)
{
FString PackageFilename;
if (FPackageName::TryConvertLongPackageNameToFilename(Pkg->GetName(), PackageFilename, Pkg->ContainsMap() ? FPackageName::GetMapPackageExtension() : FPackageName::GetAssetPackageExtension()))
{
SavePackageHelper(Pkg, PackageFilename);
}
}
UPackage::WaitForAsyncFileWrites();
// Now call base PostRun to handle final submission/notifications (or call it earlier if desired)
return Super::PostRun(World, PackageHelper, bInRunSuccess);
}
But it doesn’t work. Our nav flood tool works in editor but not from within the commandlet. It feels like the changes to the nav are not being saved. We tried calling “ChunckActor->Destroy()” within the loop just to see what happens (expecting no nav data upon loading the level in editor), but no changes were observed upong opening the level in editor. The nav was just there, and we don’t allow for nav auto-generation. We checked the timestamp of the files in Windows to make sure the files are indeed changed. We think we are missing something key in the way we load/save the nav data, but not sure where and what.
Can you help us out figuring out what we need?
Any help or suggestion is very much appreciated
Thanks a lot!
[Attachment Removed]