Quick answer: Slate caches rendered output. Bind changing values with TAttribute that points at a delegate, call Invalidate on event-driven updates, and set Volatility to Volatile for per-frame widgets.

You write a custom Slate widget showing the player’s gold count. You update the gold variable, and the widget still displays the old number. No errors, no warnings. The widget was constructed with the gold value at creation time and now it’s a snapshot. Slate widgets need to be told what to re-read each frame.

TAttribute vs. Literal

Slate supports two value patterns. A literal value is captured once at construction. A TAttribute wraps a delegate that Slate calls on every paint.

// BAD: literal captured at construction
SNew(STextBlock).Text(FText::AsNumber(PlayerGold))

// GOOD: bound to a delegate that reads the current value
SNew(STextBlock).Text(TAttribute<FText>::Create(
    TAttribute<FText>::FGetter::CreateLambda([this]() {
        return FText::AsNumber(PlayerState->Gold);
    })))

With TAttribute, every paint pass calls the lambda and reads the current gold. Changes propagate automatically.

Invalidation

Slate optimizes by caching. A widget that doesn’t ask for repaint stays with its last rendered output. After a TAttribute change, Slate may not repaint if nothing else invalidated the widget. Call Invalidate to force it:

void UMyHUDWidget::OnGoldChanged()
{
    if (GoldTextWidget.IsValid())
    {
        GoldTextWidget->Invalidate(EInvalidateWidget::LayoutAndVolatility);
    }
}

Volatility

For widgets that always need to repaint (health bars, timers, minimap), mark them Volatile:

GoldText->SetVolatile(true);

Volatile widgets skip the cache and repaint every frame. This is more CPU than invalidation-on-change, so use it only for constantly-changing values.

When to Prefer UMG

If you’re building gameplay HUD and don’t need Slate’s full control, UMG Bindings handle this pattern automatically. A bound UMG property polls at the refresh rate and invalidates correctly. Reach for direct Slate only for editor tools and performance-critical in-game UI.

Verifying

Add a UE_LOG inside the TAttribute lambda that prints the current value. If the log fires every frame, Slate is reading the bound value — any visual staleness is an invalidation bug. If the log never fires after the initial paint, the attribute is a literal.

“In Slate, always assume the widget cached the value unless you told it otherwise. TAttribute + Invalidate + Volatility are the three knobs.”

Related Issues

For UMG-specific widget issues, see Unreal UMG widget not showing on screen. For widget interaction, see Unreal widget interaction component not clicking.

Binding with TAttribute is a tiny overhead. Skip it and you’ll hunt ghost-value bugs for hours.