Description

Consider an actor defined in C++ with "bIsSpatiallyLoaded" set to true (the default), and a derived blueprint that overrides "bIsSpatiallyLoaded" to false. Now consider an actor instance of that blueprint placed in a world-partitioned map. In the Editor and while in PIE, such an actor behaves according to the BP override and is not considered spatially loaded, which results in it being loaded at all times. However, when playing in "Standalone Game" mode, the BP override is ignored and the actor incorrectly behaves according to the setting from the native base class: it is considered spatially loaded, and as such is only loaded when approached. The same problem occurs in the opposite situation.

When a world-partitioned map is loaded, execution flows through the following call chain:

UEngine::LoadMap()
UWorld::InitWorld()
ULevel::OnLevelLoaded()
UWorldPartition::Initialize()
UWorldPartition::RegisterActorDescContainer()
UActorDescContainer::Initialize()
for each FAssetData:
FWorldPartitionActorDescUtils::GetActorDescriptorFromAssetData()
FWorldPartitionActorDesc::Init()

The problem is likely related to the behavior of the last two functions, which create an "FWorldPartitionActorDesc" that is later passed to RegisterActorDescriptor():

 

[Engine\Source\Runtime\Engine\Private\WorldPartition\WorldPartitionActorDescUtils.cpp]
[:76] FWorldPartitionActorDescUtils::GetActorDescriptorFromAssetData()
[:94] TUniquePtr<FWorldPartitionActorDesc> NewActorDesc()
[:95] NewActorDesc->Init(ActorDescInitData)
[Engine\Source\Runtime\Engine\Private\WorldPartition\WorldPartitionActorDesc.cpp]
[:205] void FWorldPartitionActorDesc::Init(const FWorldPartitionActorDescInitData& DescData)
[:214] FMemoryReader MetadataAr(DescData.SerializedData, true);
[:222] FActorDescArchive ActorDescAr(MetadataAr, this)
[:223] ActorDescAr.Init()
[:225] Serialize(ActorDescAr)
[Engine\Source\Runtime\Engine\Private\WorldPartition\WorldPartitionActorDesc.cpp]
[:512] void FWorldPartitionActorDesc::Serialize(FArchive& Ar)
[:579] Ar << TDeltaSerialize<bool>(bIsSpatiallyLoaded);

 

As can be seen above, function GetActorDescriptorFromAssetData() creates a new "FWorldPartitionActorDesc", which is initialized by FWorldPartitionActorDesc::Init(). After the ActorDescAr.Init() call on line 223, we can see on a debugger that:

  • In the editor, "ActorDescAr.ClassDesc->BaseClass" refers to the correct blueprint class of the actor instance
  • In Standalone, "ActorDescAr.ClassDesc->BaseClass" is None

Afterwards, the Serialize() call on line 225 populates the "FWorldPartitionActorDesc" structure, including its variable "bIsSpatiallyLoaded" on line 579. Now we can see that:

  • In the editor, "bIsSpatiallyLoaded" receives the correct value from the BP class override
  • In Standalone, "bIsSpatiallyLoaded" receives the incorrect value from the native base class
Steps to Reproduce

1. Download the attached repro project
2. There are 2 C++ actors in the project:
2.1. ANonSLBase: This simply sets bIsSpatiallyLoaded to false in the constructor.
2.2. ASLBase: This simply sets bIsSpatiallyLoaded to true in the constructor.
3. There are 4 BP actors in the project:
3.1. BP_NonSLBase_NonSL - Derived from ANonSLBase, keeps bIsSpatiallyLoaded as false
3.2. BP_NonSLBase_SL ---- Derived from ANonSLBase, overrides bIsSpatiallyLoaded to true
3.3. BP_SLBase_NonSL ---- Derived from ASLBase, overrides bIsSpatiallyLoaded to false
3.4. BP_SLBase_SL ------- Derived from ASLBase, keeps bIsSpatiallyLoaded as true
4. The world-partitioned startup map contains one actor instance of each BP type above.
5. Play in the selected viewport or a new window:
5.1. Actors from NonSL blueprints are always loaded (regardless of the CPP base class)
5.2. Actors from SL blueprints are loaded when approached (regardless of the CPP base class)
6. Play as "Standalone Game":
6.1. Actors from NonSL base class are always loaded (regardless of their blueprint class)
6.2. Actors from SL base class are loaded when approached (regardless of their blueprint class)

Have Comments or More Details?

There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-227634 in the post.

0
Login to Vote

Unresolved
CreatedOct 15, 2024
UpdatedOct 16, 2024
View Jira Issue