In-world widget cannot display a texture read from icon_component.Icon of a runtime-instantiated prefab

Summary

An in-world widget entity (the generated WBP_X_entity class of a Widget Blueprint) shows its default texture instead of a texture that was read from icon_component.Icon of an entity created at runtime from a prefab (Prefab{}). The same texture is displayed correctly when it comes from an @editable texture field, or from an icon_component of an entity placed in the level. The same value, read the same way, is displayed correctly in a screen (player UI) widget.

Please select what you are reporting on:

Unreal Editor for Fortnite

What Type of Bug are you experiencing?

UI/Tools

Steps to Reproduce

  1. Create a Widget Blueprint WBP_ReproIcon with one Image and one Verse field IconTexture : texture (default: any texture).
    Bind IconTexture to the image’s Brush with the standard texture-to-brush conversion.
  2. Create a prefab with an icon_component, and pick a texture in its Details panel (texture 3).
  3. Place two entities in the level:
    • one with an icon_component, with a texture picked in the Details panel (texture 2);
    • one with the component below. Set its EditableTexture to a third, different texture (texture 1),
      IconSourceEntity to the first entity, and PrefabType to the prefab from step 2.
      Use three clearly different textures, so a missing update is visible.
  4. Run the level and watch the widget for about 20 seconds. Phases A to D repeat every 5 seconds, and each logs a [Repro] Phase X line.
    The image should show texture 1, then texture 2, then texture 3 (phase C), then texture 3 again (phase D).
    Instead it stays on texture 2 during phases C and D.
using { /Verse.org/SceneGraph }
using { /Verse.org/Simulation }
using { /Verse.org/Assets }

in_world_icon_repro_component := class<final_super>(component):

    @editable
    EditableTexture : ?texture = false

    @editable
    IconSourceEntity : entity = entity{}

    @editable
    PrefabType : ?concrete_subtype(entity) = false

    @editable
    PhaseSeconds : float = 5.0

    OnSimulate<override>()<suspends>:void=
        (super:)OnSimulate()
        if(SimEntity := Entity.GetSimulationEntity[]):
            Widget := WBP_ReproIcon_entity{}
            SimEntity.AddEntities(array{ Widget })
            Widget.SetGlobalTransform(Entity.GetGlobalTransform())
            Sleep(PhaseSeconds)
            RunPhases(Widget)

    RunPhases(Widget:WBP_ReproIcon_entity)<suspends>:void=
        loop:
            # Phase A
            if(Texture := EditableTexture?):
                set Widget.IconTexture = Texture
            Sleep(PhaseSeconds)

            # Phase B
            if(IconComp := IconSourceEntity.GetComponent[icon_component]):
                set Widget.IconTexture = IconComp.Icon
            Sleep(PhaseSeconds)

            # Phase C
            if(Prefab := PrefabType?):
                Instance := Prefab{}
                if(IconComp := Instance.GetComponent[icon_component]):
                    set Widget.IconTexture = IconComp.Icon
            Sleep(PhaseSeconds)

            # Phase D
            if(Prefab := PrefabType?, SimEntity := Entity.GetSimulationEntity[]):
                Instance := Prefab{}
                SimEntity.AddEntities(array{ Instance })
                Sleep(1.0)
                if(IconComp := Instance.GetComponent[icon_component]):
                    set Widget.IconTexture = IconComp.Icon
                Instance.RemoveFromParent()
            Sleep(PhaseSeconds)

Expected Result

set Widget.IconTexture = SomeEntity.GetComponent[icon_component].Icon updates the image in the in-world widget,
regardless of how the entity was created.

Observed Result

Each source uses a different texture, so a change is visible. “Shows the new texture” means the image changed to that
source’s texture. “No change” means the image stays on the texture from the previous phase.

Phase Texture source In-world widget
A @editable texture on a component Shows the new texture
B icon_component.Icon of an entity placed in the level (texture picked in the Details panel) Shows the new texture
C icon_component.Icon of an instance of an editor-authored prefab, created at runtime with Prefab{} No change (still shows phase B’s texture)
D Same as C, but the instance is added to the simulation (AddEntities) and one second passes before the icon is read No change (still shows phase B’s texture)

Platform(s)

UEFN, PC.

Additional Notes

What we ruled out

  • The widget and its binding. Phases A and B use the same widget and binding and work.
  • The texture asset. The texture used by the prefab in phases C and D is a normal project texture and displays
    correctly when set through the other sources.
  • Scene membership and time. Phase D adds the instance to the simulation and waits; it still fails. In the original game
    project we also waited several seconds after creating an instance, with and without adding it to the scene.
  • The value itself. In the original project the same icon_component.Icon value, read from the same item entity,
    displayed correctly in a screen widget, and the item’s name (from description_component) was correct. Only the in-world
    widget fails.
  • Presentation and timing of the widget. Setting a hard-coded texture on the same widget at the same moment works,
    and we tested making the widget visible to everyone and re-applying the value after a delay.
  • Nested widgets. The original project routes the texture through a child widget; the minimal repro uses a single image
    and fails the same way.

Workaround

Do not read the icon from the runtime-created entity for in-world widgets. Keep an @editable list of
{ItemID, texture} entries on a component and read the texture from that list. We use this in the game
and the in-world widget then displays the textures correctly.