#loading stuff

1 messages · Page 1 of 1 (latest)

blazing quest
#

thread Iguess

#
void UMachineSubsystem::PostInitialize()
{
    FLevelStreamingDelegates::OnLevelStreamingStateChanged.AddUObject(this, &UMachineSubsystem::OnLevelStateChanged);

    const UMachineSettings* set = GetDefault<UMachineSettings>();
    check(set);

    MinWorldThawTime = set->MinWorldThawTime;
    MaxWorldThawTime = set->MaxWorldThawTime;
    TotalWorldThawTimer = 0.f;
    WorldThawTimer = 0.f;
}
#
void UMachineSubsystem::Tick(float DeltaTime)
{
    if (bIsWorldThawed)
    {
      // My main logic in this Subsystem...
    }
    else
    {
        WorldThawTimer += DeltaTime;
        TotalWorldThawTimer += DeltaTime;

        if (WorldThawTimer > MinWorldThawTime && AwaitingLevels.IsEmpty())
        {
            ThawWorld();
        }
        else if (TotalWorldThawTimer > MaxWorldThawTime)
        {
            UE_LOGFMT(LogMachinesSubsystem, Warning, "World thaw took longer than {0} seconds!", MaxWorldThawTime);
            ThawWorld();
        }
    }
}
#
void UMachineSubsystem::OnLevelStateChanged(UWorld* InWorld, const ULevelStreaming* InStreamingLevel, ULevel* LevelIfLoaded, ELevelStreamingState PreviousState, ELevelStreamingState NewState)
{

    if (!IsValid(InStreamingLevel))
        return;

    FName stream_name = InStreamingLevel->GetFName();

    if (NewState == ELevelStreamingState::MakingVisible)
    {
        WorldThawTimer = 0.f;
        AwaitingLevels.Add(stream_name);
        UE_LOGFMT(LogMachinesSubsystem, Verbose, "Waiting for {0} to finish streaming ({1} levels in queue)...", stream_name, AwaitingLevels.Num());
    }

    if (NewState == ELevelStreamingState::LoadedVisible)
    {
        AwaitingLevels.Remove(stream_name);
        UE_LOGFMT(LogMachinesSubsystem, Verbose, "Level {0} finished streaming ({1} levels in queue).", stream_name, AwaitingLevels.Num());
    }
}

void UMachineSubsystem::ThawWorld()
{
    bIsWorldThawed = true;
    UE_LOGFMT(LogMachinesSubsystem, Log, "World is being thawed after {0} seconds.", TotalWorldThawTimer);
    OnWorldThawed.Broadcast();
}
#

And the player (and anything else that needs the world stable) just subscribes to OnWorldThawed.

#

I think that's it.

#

It works well for us.

#
#include "Logging/StructuredLog.h"
#include "Streaming/LevelStreamingDelegates.h"
sonic topaz
#

@blazing quest Hey again, let me know if you don't want me to ping you like this here - I'm curious why have you chosen to use if (NewState == ELevelStreamingState::MakingVisible) for adding awaiting levels, rather than e.g. ELevelStreamingState::Loading?

I doubt that it matters too much, just trying to understand if there's some particular reason why it might be a good idea to avoid Loading (e.g. that state might skipped or something).

blazing quest
#

I can't say with 100% certainty, but I believe I tried Loading first but found that it wasn't called.

#

I remember I debug printed various events to the log and just picked one that seemed reliable.

sonic topaz
#

Thanks, hm I was afraid it might be something like that... it seems like e.g. here https://zomgmoz.tv/unreal/ALevelInstance-actor-in-packaged-and-standalone-builds tried binding to Streaming->OnLevelLoaded.AddDynamic(this, &ThisClass::LevelLoaded); (an event inside the ULevelStreaming that you can bind to) and it didn't get called.

So I'm wondering whether their meaning of "loaded/loading" in this context might correspond to something different... it doesn't seem like it from looking at source though. I thought it might correspond to the "event" when the "should be loaded" is changed on the ULevelStreaming object, but it doesn't seem to be the case.

blazing quest
#

I'll admit I didn't dig very deep into the timing of the various events, I mostly went by trial and error.

sonic topaz
#

Oh right that's fine, just curious about what the heck is happening... but I'll probably just end up relying on the visibility state too.. if it works it works.

blazing quest
#

In our case I wanted to be notified about everything, both sublevels and LVI:s -- are you mainly interested in knowing when specific LVI:s are loaded?

#

I think the MakingVisible state gets called quite early for the record, before any chunky stuff (like meshes) gets loaded.

sonic topaz
#

Hm well nothing in particular right now, just trying to see what the options are. And curious about the seemingly buggy behavior when it comes to "on loaded" / loading start events getting skipped.

blazing quest
#

Yeah, maybe it has to do with WorldPartition?

#

You're also using traditional Level Streaming, if I remember right?

sonic topaz
#

Yeah.

One thing that occurs to me that the load could correspond to the actual UPackage loading -> it being loaded really just means the UPackage object has been created. So if it's already been created, loading event won't be triggered again? E.g. if you decide to stream in the same level twice loading event might only get triggered on the first one?). No idea, just making vague guesses.