[Bug Report] SubLevel assigned to LevelStreamingVolume re-loading randomly when traveling through world

Branch:
Binary

Build Version:
4.7.0-2467323

Repro Steps:

  • Create new blank project “LevelVolume” with no starter content
  • Create new LevelStreamingVolume
  • Position LevelStreamingVolume at 0,0,0
  • Scale LevelStreamingVolume to 100000,100000,100000
  • Create new sublevel level “SubLevel” in Levels window
  • Add LevelStreamingVolume to “Streaming Volumes” property of “SubLevel” in “Level Details” window
  • Open “Output Log” window
  • Hit “Play” and don’t move mouse
  • While not moving mouse, Move camera forward and back with “W” and “S” while still keeping ground in view

Result:

Notice that in output log you will see:

LogWorld: PIE: Copying PIE streaming level from /Game/SubLevel.SubLevel to /Game/UEDPIE_0_SubLevel.SubLevel. OwningWorld: /Temp/UEDPIE_0_Untitled_1.Untitled_1

LogWorld: PIE: Copying PIE streaming level from /Game/SubLevel.SubLevel to /Game/UEDPIE_0_SubLevel.SubLevel. OwningWorld: /Temp/UEDPIE_0_Untitled_1.Untitled_1

LogWorld: PIE: Copying PIE streaming level from /Game/SubLevel.SubLevel to /Game/UEDPIE_0_SubLevel.SubLevel. OwningWorld: /Temp/UEDPIE_0_Untitled_1.Untitled_1

LogWorld: PIE: Copying PIE streaming level from /Game/SubLevel.SubLevel to /Game/UEDPIE_0_SubLevel.SubLevel. OwningWorld: /Temp/UEDPIE_0_Untitled_1.Untitled_1

LogWorld: PIE: Copying PIE streaming level from /Game/SubLevel.SubLevel to /Game/UEDPIE_0_SubLevel.SubLevel. OwningWorld: /Temp/UEDPIE_0_Untitled_1.Untitled_1

LogWorld: PIE: Copying PIE streaming level from /Game/SubLevel.SubLevel to /Game/UEDPIE_0_SubLevel.SubLevel. OwningWorld: /Temp/UEDPIE_0_Untitled_1.Untitled_1

LogWorld: PIE: Copying PIE streaming level from /Game/SubLevel.SubLevel to /Game/UEDPIE_0_SubLevel.SubLevel. OwningWorld: /Temp/UEDPIE_0_Untitled_1.Untitled_1

LogWorld: PIE: Copying PIE streaming level from /Game/SubLevel.SubLevel to /Game/UEDPIE_0_SubLevel.SubLevel. OwningWorld: /Temp/UEDPIE_0_Untitled_1.Untitled_1

LogWorld: PIE: Copying PIE streaming level from /Game/SubLevel.SubLevel to /Game/UEDPIE_0_SubLevel.SubLevel. OwningWorld: /Temp/UEDPIE_0_Untitled_1.Untitled_1

Each one of those lines is “SubLevel” being reloaded. However this is not supposed to happen since player was always inside LevelStreamingVolume

Notes:

Making level streaming volume small will probabilistically avoid this issue. While size of level streaming volume that I need for my game is not as large as volume used for this bug report I am still occasionally experiencing sublevel reloads.

bug is easily seen when LevelStreamingVolume’s size is exaggerated and that is why it’s so large in this bug report.

I also explored Unreal’s source code to figure out why this problem was happening.

In commit: b613e1c103c971412e2a834f3c5f074f37875d99

I found that problem could be seen in:

Engine/Source/Runtime/Engine/Private/LevelTick.cpp line 597:
bViewpointInVolume = StreamingVolume->EncompassesPoint( ViewLocation );

variable “ViewLocation” is a 3D point and “EncompassesPoint” evaluates to false for certain values of “ViewLocation” even tho “ViewLocation” is encompassing “StreamingVolume”.

Following execution of “EncompassesPoint” I ended up at:

Engine/Source/Runtime/Engine/Private/PhysicsEngine/BodyInstance.cpp line 3592:
float SqrDistance = PxGeometryQuery::pointDistance(PPoint, PGeom, PGlobalPose, &PClosestPoint);

Call Stack:

UE4Editor-Engine-Win64-Debug.dll!FBodyInstance::GetDistanceToBody(const FVector & Point, FVector & OutPointOnBody) Line 3594	C++
UE4Editor-Engine-Win64-Debug.dll!UPrimitiveComponent::GetDistanceToCollision(const FVector & Point, FVector & ClosestPointOnCollision) Line 795	C++
UE4Editor-Engine-Win64-Debug.dll!AVolume::EncompassesPoint(FVector Point, float SphereRadius, float * OutDistanceToPoint) Line 63	C++
UE4Editor-Engine-Win64-Debug.dll!UWorld::ProcessLevelStreamingVolumes(FVector * OverrideViewLocation) Line 597	C++

function “pointDistance” is a PhysX function that is supposed to return 0 if “PPoint” is inside “PGeom”.

But “pointDistance” returns > 0 for some “PPoints” that are inside “PGeom”. Thus telling Unreal to unload level and then reload level once your character moves and “PPoint” changes.

Foot Note

That’s all I could find out about problem. I know that PhysX will be opening up their source code to Unreal Engine but in version I have I still don’t have access to PhysX’s source code. So I can’t keep digging inside “pointDistance” function.

Hi Mastodon,

Thanks for thorough investigation! I was able to reproduce this in 4.7.2, but it looks like it’s already been fixed in our main internal branch. fix will probably be implemented in 4.8. Hope that helps!

Awesome! Glad to hear it’s fixed in 4.8.

Thanks for looking into it .