Assert when trying to load duplicates of a level instance containing a packed level actor

Hello!

I’m getting the following assert when trying to spawn in a Level Instance (LI) which contains a Packed Level Actor (PLA):

Assertion failed: GIsReinstancing || Value == nullptr || Value == LevelInstance [File:..\Engine\Source\Runtime\Engine\Private\LevelInstance\LevelInstanceSubsystem.cpp] [Line: 199]

Engine version - 5.7.1 source build

I’m using ULevelStreamingDynamic::LoadLevelInstanceBySoftObjectPtr to load in my level instance. I’m not using World partitioning on my map.

Edit - This is all editor time generation. My intention is to not use this for runtime generation.

After some initial debugging, I can confirm that the GUID for the PLA in the LI that spawns after the first one is the same which causes Value == LevelInstance to be true and the assert to fire in ULevelInstanceSubsystem::RegisterLevelInstance.

The PLA only contains HierarchicalInstancedStaticMeshes.

I can also confirm that this assert doesn’t fire if the PLA is removed from the LI.

I’ve got a couple of ideas for fixing this but I’m not sure if that’s the intended way to approach this.

Idea 1 - Remove PLAs from the LIs and spawn them separately

Idea 2 - Create a new child class of APackedLevelActor and use it instead of the default one. Then give it a new GUID in PostInitializeComponents. I’m not sure what the consequences of this could be.

I would like to keep using the workflow of having PLA(s) in LIs but I’m open to pivot if required :slight_smile:

[Attachment Removed]

Steps to Reproduce

Steps to reproduce:

  1. Create a packed level actor containing HierarchicalInstancedStaticMeshes or StaticMeshes
  2. Create a level instance with the above packed level actor
  3. While in the editor, try to load 2 or more of the above level instances using ULevelStreamingDynamic::LoadLevelInstanceBySoftObjectPtr or ULevelStreamingDynamic::LoadLevelInstance via a function callable in the editor
  4. Observe that the assert fires for all instances after the first one
    [Attachment Removed]

Hi,

The assert you are hitting means there is a collision when the FLevelInstanceID is generated. This value is hashed in the constructor of the class. I recommend debugging there to understand where is the collision coming from. I suspect the LevelInstanceActor is not stable for networking (IsNameStableForNetworking).

I recommend that you change the way the new instances are created. The regular editor paths are doing it through the UActorFactory when the Level is dragged from the content browser. The spawned LevelInstanceActor registers to the subsystem and then trigger a load of the level. This is different from what you seem to be doing.

Regards,

Martin

[Attachment Removed]

Hi,

It should be fine to do it using the ULevelInstanceActorFactory directly.

Martin

[Attachment Removed]

Hi [mention removed]​!

Thank you for getting back on this :slight_smile:

I have debugged how the FLevelInstanceID is generated and the conflict is coming from FLevelInstanceActorGuid::GetGuid_Internal. In the editor, the code that executes is this:

const FGuid& Guid = (!Actor->GetWorld() || !Actor->GetWorld()->IsGameWorld() || !Actor->GetIsReplicated() || Actor->HasAuthority()) ? Actor->GetActorGuid() : ActorGuid;

Since it is not the game world, it defaults to using the Actor->ActorGuid for the packed level actor in level instance. This causes the generated FLevelInstanceIDs to be the same for all spawned PLAs in the duplicated level instances and hits the assert.

“I recommend that you change the way the new instances are created. The regular editor paths are doing it through the UActorFactory when the Level is dragged from the content browser”

(Apologies if this sounds stupid ('^.^))

I looked at how level instances are spawned when you drag and drop them in the editor. As my use case is primarily to spawn the level instances in the editor and not at runtime, would you recommend going via the placement subsystem or directly via the ULevelInstanceActorFactory?

Thanks again for your help so far!

Regards,

Tanuj

[Attachment Removed]

Thanks Martin! I’ll give it a go and get back to you on this. :slight_smile:

[Attachment Removed]

Hey Martin!

Apologies for the late reply. I can confirm that spawning the level instances using this method no longer causes the assert.

Spawning in a new ALevelInstance and then assigning it the asset and then loading it also does the job for me and I’ll be using that instead of the factory method for now.

Thanks for helping out :slight_smile:

[Attachment Removed]