I’m working on a large world composition level. The navigation data re-build keeps popping up and slowing things down. There appears to be no setting that will prevent it from doing so when in the editor.
First: Is there a setting that’s supposed to do this?
Second: It seems the rebuild is triggered from this code:
void UNavigationSystemV1::RebuildDirtyAreas(float DeltaSeconds)
{
SCOPE_CYCLE_COUNTER(STAT_Navigation_TickMarkDirty);
UWorld* World = GetWorld();
const bool bForceRebuilding = (World != nullptr) && (World->IsGameWorld() == false);
DefaultDirtyAreasController.Tick(DeltaSeconds, NavDataSet, bForceRebuilding);
}
Note that any world that’s not a “Game World” will cause re-builds, and at least the persistent level is an editor world (I think all the levels might be.)
This calls:
void FNavigationDirtyAreasController::Tick(const float DeltaSeconds, const TArray<ANavigationData*>& NavDataSet, bool bForceRebuilding)
{
DirtyAreasUpdateTime += DeltaSeconds;
const bool bCanRebuildNow = bForceRebuilding || (DirtyAreasUpdateFreq != 0.f && DirtyAreasUpdateTime >= (1.0f / DirtyAreasUpdateFreq));
if (DirtyAreas.Num() > 0 && bCanRebuildNow)
...
It’s also interesting that DirtyAreasUpdateFreq is per-second, not seconds-per-rebuild. That’s not super obvious from the tool tip on that setting …
So, what will go wrong if I make a checkbox named “bSuppressNavigationAutoRebuildInEditor” and check it in the bForceRebuilding part?
I’m hoping that “Build Paths” in the overall build process will still re-build as necessary.
It turns out that there is a flag called bNavigationAutoUpdateEnabled, but it’s not easily accessible through the settings UI.
It’s also … toggled each time a world is loaded, to force the “set” function to pay attention to it. Blech!
if (Mode == FNavigationSystemRunMode::EditorMode)
{
// make sure this static get applied to this instance
bNavigationAutoUpdateEnabled = !bNavigationAutoUpdateEnabled;
SetNavigationAutoUpdateEnabled(!bNavigationAutoUpdateEnabled, this);
void UNavigationSystemV1::SetNavigationAutoUpdateEnabled(bool bNewEnable, UNavigationSystemBase* InNavigationSystemBase)
{
if (bNewEnable != bNavigationAutoUpdateEnabled)
{
bNavigationAutoUpdateEnabled = bNewEnable;
UNavigationSystemV1* NavSystem = Cast<UNavigationSystemV1>(InNavigationSystemBase);
if (NavSystem)
{
const bool bCurrentIsEnabled = NavSystem->GetIsAutoUpdateEnabled();
virtual bool GetIsAutoUpdateEnabled() const { return bNavigationAutoUpdateEnabled; }
So bCurrentIsEnabled will always be the same value as bNewEnable.
This is the worst kind of globals/statics usage that gives C++ a bad name.