Inventory + Hotbar UI (UMG Widgets, updated dynamically from replicated data)

We’ve encountered a persistent issue with UMG UImage widgets that stop updating after many refresh cycles (~30–35 iterations).
This happens in a dynamic inventory system where slot widgets (UInventorySlotWidget) are updated frequently via SetBrushFromTexture() calls.

The behavior is consistent and not related to replication or logic bugs — data is correct, but the image just disappears or “sticks” visually until the entire UI is rebuilt or reopened.


Reproduction Steps:

  1. Create an inventory UI (e.g. 8 slots) with UImage used as item icons.

  2. Repeatedly move items between inventory and hotbar (drag & drop), so that SetBrushFromTexture() is called frequently.

  3. After about 30–35 swaps, the icon stops updating — visually blank, even though data is valid.

  4. Closing and reopening the UI restores the correct icon (confirming that the data itself is fine).


Expected:

UImage::SetBrushFromTexture() should always refresh the underlying Slate brush and redraw the texture, regardless of how many times it’s called.

Actual:

After multiple updates (approx. 30+), the Slate render tree seems to stop invalidating the brush.
The image widget still exists, but doesn’t render the assigned texture until the widget tree is fully rebuilt.


Workarounds Tried (Partial Results):

  • Rebuilding all slot widgets (RemoveFromParent() + CreateWidget()) every 15 updates — works temporarily, but is a hack.

  • Using ForceLayoutPrepass() or SynchronizeProperties()no effect.

  • Creating a new FSlateBrush each time with SetResourceObject()reduces frequency of the issue but doesn’t fully eliminate it.

  • Simple InvalidateLayoutAndVolatility() on the UImage doesn’t fix it.


Suspected Cause:

Slate may be caching the same brush resource and skipping re-draw when textures are swapped too frequently, leading to the render state not being invalidated.

It might be related to an internal optimization in SImage or the underlying FSlateBrush pool when the same UObject pointer (texture) is used repeatedly across frames.


Questiont:

  • Is this a known Slate invalidation bug or regression in UE5.6?

  • Is there a proper way to fully invalidate an SImage or force the brush to redraw (beyond rebuilding the widget)?

  • Any official workaround to ensure UMG Images update correctly during frequent brush updates?

void UInventorySlotWidget::UpdateSlot_Implementation(const FInventorySlot& SlotData, const FItemData& ItemData)
{
if (UImage* Icon = Cast(GetWidgetFromName(TEXT(“ItemIcon”))))
{
FSlateBrush NewBrush;
if (ItemData.Icon)
{
NewBrush.SetResourceObject(ItemData.Icon);
NewBrush.ImageSize = FVector2D(64.f, 64.f);
Icon->SetBrush(NewBrush);
Icon->SetVisibility(ESlateVisibility::Visible);
}
else
{
Icon->SetBrush(FSlateBrush());
Icon->SetVisibility(ESlateVisibility::Hidden);
}

    Icon->InvalidateLayoutAndVolatility();
    Icon->ForceLayoutPrepass();
}

}