UserWidget never updates because it is "occluded", but it's visible on the screen.

In moving our project from UE 4.27 to UE 5.5 I was passed a bug that two world space custom UserWidget elements weren’t appearing.

It seems like the problem is that they aren’t updating because they’re “occluded” but I’m looking at them right now in the viewport so I’m puzzled about how this can be the case or how to proceed in fixing this. There must be something unique to our project that is somehow “occluding” them. How do I debug this? Are there some visual tools that could indicate the occlusion areas of the space? It doesn’t seem like they should be being occluded so something weird and unusual is going on.

(I’m assuming that this optimization was added in UE5 and this is why it works in our old project?)

----

I was able to confirm that they were indeed in the scene by forcing the widgets to be visible. The reason they weren’t appearing normally was because their intro animation was never playing despite being called, and this was because their NativeTick() was never being called.

I was able to force things to work as expected by replacing the if ( ShouldDrawWidget() ) line at 1255 of WidgetComponent.cpp with if (true) to force the widgets to draw.

It appears as if the widgets fail the ShouldDrawWidget() call because they were not recently rendered and this is because I never entered this block in SceneVisibility.cpp and updated the component render time.

// Update the last component render time only if we know for certain the primitive is un-occluded. if (View.PrimitiveDefinitelyUnoccludedMap[BitIndex] || View.Family->EngineShowFlags.Wireframe) { const bool bUpdateLastRenderTimeOnScreen = true; PrimitiveSceneInfo->UpdateComponentLastRenderTime(CurrentWorldTime, bUpdateLastRenderTimeOnScreen); }

Creating a test level in our project with basic custom UserWidget I was able to get a UserWidget to have its NativeTick() called as expected. Additionally I was able to confirm the functionality where it is not ticked if occluded by moving the camera away from looking at it.

So the weird thing is however that in the existing level these UserWidgets do seem like they’re within the viewport. I don’t know if I’m missing something, if there is some way that their bounds or position are not where they appear to be?

As an aside I’m a bit troubled by this optimization functionality as we are expecting to animate into view one of these widgets from “off screen” and so if it is being culled and not updated because some part of its position is out of view then I don’t know how we’d implement this “animate in” functionality.

Hi,

There should be a “Tick When Offscreen” flag on the WidgetComponent, does it work if you set that to true? We also have tick modes which you can use to determine if we should try and optimize by stopping ticks while offscreen (Automatic) or tick all the time (Enabled). Much of this was added in 4.27 so I’m not sure if that explains the change in behavior, but it’s worth double checking those settings in case something broke in the upgrade.

I did find an open issue that might be relevant here, WidgetComponent is not updated with occlusion culling disabled. If that’s the culprit here, are you happy with the workaround of leaving Tick When Offscreen enabled? If there are performance concerns, you could try and toggle it manually at the moments when you know the widget will need to tick.

For visualizing the widget bounds, it can be helpful to temporarily wrap the whole thing in a border (or something visible) so you can see what is actually coming through on the widget component. I’ve seen some odd issues where a widget component’s contents featured a canvas panel with widgets in the lower right, and the Draw Size prevented anything from actually appearing (since it’s going to index from the top left corner. Typically “Draw at Desired Size” is a better option than hardcoding a size, unless your content widget is set to scale and you want to drive the size dynamically from the component.

Best,

Cody

Ok very interesting and helpful stuff.

The “Tick When Offscreen” did indeed work (huzzah!). That would be a fine fix as we’re using this widget in tight circumstances and are already heavily managing its enabled/disabled state.

Looking at it further however, we have indeed disabled occlusion culling (which is a bit surprising to me) and so enabling that also fixes the problem. That feels like the better fix to me but I’ll have to check in with the team in case there was some particular reason we’d turned occlusion culling off.

I think we can consider this fixed tho. Both your suggestions are viable solutions. thx! :slight_smile: