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
- Create a Widget Blueprint
WBP_ReproIconwith oneImageand one Verse fieldIconTexture : texture(default: any texture).
BindIconTextureto the image’sBrushwith the standard texture-to-brush conversion. - Create a prefab with an
icon_component, and pick a texture in its Details panel (texture 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
EditableTextureto a third, different texture (texture 1),
IconSourceEntityto the first entity, andPrefabTypeto the prefab from step 2.
Use three clearly different textures, so a missing update is visible.
- one with an
- 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 Xline.
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.Iconvalue, read from the same item entity,
displayed correctly in a screen widget, and the item’s name (fromdescription_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.