Build lighting data missing after setting level invisible and then visible again in a packaged build

Hey, we upgraded our project from 5.3 to 5.5 and noticed an issue where the build lighting data gets lost in a packaged Development build with our level streaming approach.

We create and load levels with ULevelStreamingDynamic objects. We then keep the levels in memory and only set the visibility with ULevelStreaming::SetShouldBeVisible.

When loading the level the first time the lighting is correct. After hiding it and showing it again the lighting is wrong.

After unloading the level and loading it again the lighting is correct again. So it seems that setting the visibility now also clears the build lighting data?

With “ENABLEALLSCREENMESSAGES” you can see the typical error print message: LIGHTING NEEDS TO BE REBUILD (309 unbuild objects)

In UE5.3 it still works and I try to figure out how to fix this.

I’ll try to create a simple reproducer project for you, but maybe you already have an idea what might be causing this?

BR,

Dominikus

Here is the minimal reproducer I created.

It loads an empty (black) startup map and you can set the LevelStreamingDynamic-Objects (the level with the meshes and baked lighting) visibility and loaded state with the buttons 2 to 4.

When you package it and run it you’ll notice that the light data gets lost after setting the streaming levels visibility to hidden once. After unloading & loading it again it will also display the lighting properly again.

I continued with my investigation and it seems like the lighting data is not lost but rather a mix between the build lighting and the unbuild lighting. I’ll demonstrate what I mean with pictures from the Reproducer-Project that I attached:

This is how it should look like with the build lighting data: (in a Development Build)

[Image Removed]

This is how it looks without lighting data, I called “Level->GetOrCreateMapBuildData()->InvalidateStaticLighting(World);” :

[Image Removed]

And now our issue after hiding the level once and then setting it visible again:

[Image Removed]I also get the same in the editor if I call Level->GetOrCreateMapBuildData()->InvalidateSurfaceLightmaps(World);

I still couldn’t find a proper solution to fix this.

However I implemented a workaround for us which basically checks if a level has a MapBuildData and then unloads and loads it instead of hiding and making it visible.

This however, as expected, reduces the performance drastically and I’d appreciate another proposal for a fix / workaround.

Is it possible to copy the MapBuildData after loading a level, to then override it after we set it invisible and it gets corrupted?

Or do you have another idea so I can rollout a quick solution for our product?

Hi,

thanks for reporting the issue and providing a repro project. I could reproduce the issue in 5.5 and 5.6, but not in 5.3 or 5.4, which seems to indicate this first started with 5.5 (potentially with this commit which treats static lighting differently between editor and cooked builds, but I have not been able to confirm this yet).

I don’t have a firm idea what could cause this behaviour, but I don’t think MapBuildData getting corrupted is the issue since toggling its visibility happens instantly. It seems to me that unhiding the level somehow sets the point light’s mobility to stationary instead of static, while retaining the baked lighting.

I will file a bug report with Epic for this and will post a link here when it becomes available on the public issue tracker.

Best,

Sam

Hey Sam,

thanks for pointing out that the lights mobility might be the issue. I am not too familiar with the engine code about lighting so I am just trying a lot of stuff out to fix this.

For us the issue is blocking our 5.5 Upgrade and I need to find a workaround regardless of whether it gets fixed in 5.6. Since we don’t build the engine source we cannot modify engine code to cherry pick the fix in the future anyways.

I could fix the static <-> stationary light problem by caching all static lights FPrecomputedLightInstanceData when they get loaded. After setting the level hidden or visible I always override their component data with ApplyComponentInstanceData(…). I guess the issue here is related to the OriginalLightGuid and the LightGuid. But it seems like the light wasn’t the only issue, since the image is still different.

Now instead of the completely wrong image as you can see in the reproducer:

[Image Removed]I get the following:[Image Removed]This is already better, but the meshes are still being affected by some additional lighting?

I tried to experiment with the StaticMeshComponents LODData and the saved MapBuildDataId in a similar way as with the light GUID but the result didn’t change.

Do you maybe have an idea what could be the issue with the meshes and how I could work around the issue?

Hi,

I have reported the issue to Epic. It’s available on the public issue tracker at this link, so its progress can be tracked.

I understand that a potential fix in 5.6 or later will not help your case. I looked into the issue with the additional lighting on the meshes after making the map visible again, but I have not been able to narrow down why that happens or come up with a workaround. If you want, I can pass this to Epic so someone with more knowledge of this part of engine can have a look. Please let me know.

Thanks,

Sam

Hey,

thanks for opening the bug ticket!

Since we need this fixed for the engine upgrade and we can’t continue here on our own without further guidance / support, I’d really appreciate it if you would pass this to someone from Epic.

Thanks,

Dominikus

Hi,

I have been able to confirm that the regression started with this commit, and have re-assigned the ticket to a subject matter expert at Epic.

Best regards,

Sam

Hi Dominkus, it might that you’re missing those 2 cls in which we submitted fixed related to StaticLighting & Levels, 37625645 + 42826038.

If this doesn’t fix it, can you verify if the LightGuid or the for the light components or MapBuildDataId in FStaticMeshComponentLODInfo for actors in those levels are unchanged?

Hey Dominic,

we use the vanilla engine version from the launcher so we won’t be able to cherry pick a fix.

We actually found a fix in the meantime which is exactly what I mentioned before in the post.

As you suspected the LightGuids and MapBuildDataIds changed after hiding a level.

To fix this issue we cache the relevant data after initially loading a map:

TMap<FWeakObjectPtr, FPrecomputedLightInstanceData> StaticLightData; TMap<FWeakObjectPtr, FPrecomputedSkyLightInstanceData> StaticSkylightData; TMap<FWeakObjectPtr, TStructOnScope<FActorComponentInstanceData>> StaticMeshData;With the Light- and Skylightdata we were able to just apply them with ApplyComponentInstanceData(…).

The static meshes however had some conditions that prevented us from using a similar function. That’s why we needed to iterate over the LODData and set the GUIDs directly.

This is an ok fix for us and we went live with it on monday.

I guess we can close the ticket now.

We’ll attempt to repro this internally to work on a fix. Glad you have a work around for now.