Download

UWidgetComponent and UUserWidget - Native construct runs too late to update widget on begin play

Hi guys,

I have a widget component that is created on BeginPlay for my actor, basically they have a hud element above them.

The component then runs a few commands to setup the visibility of the widget it controls, however i’m noticing that the Widget component functions are run before the widget NativeConstruct is run, and i believe this is causing the values i want to set (for example the widget has a text box that is updated to display the actor name) to not update.
(1 in the image below)


void AIGCCarryableBase::BeginPlay()
{
    Super::BeginPlay();

    // Only create HUD component if we have a HUD
    if (GetHasHud())
    {
        WidgetComponent = NewObject<UIGCCarryableWidgetComponent>(this, UIGCCarryableWidgetComponent::StaticClass(), (TEXT("UIWidget")));

        if (WidgetComponent)
        {
            WidgetComponent->RegisterComponent();
            WidgetComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::SnapToTargetIncludingScale, NAME_None);

            if (GetIsVicinityBasedHUD())
            {
                WidgetComponent->UpdateTextField(EWidgetElementOptions::WEO_TextField1, GetName());
                WidgetComponent->bDisplayElement(EWidgetElementOptions::WEO_TextField1, false);
                WidgetComponent->bDisplayElement(EWidgetElementOptions::WEO_ProgressBar1, false);
                WidgetComponent->bDisplayElement(EWidgetElementOptions::WEO_ProgressBar2, false);
                WidgetComponent->bDisplayElement(EWidgetElementOptions::WEO_ProgressBar3, false);
                GEngine->AddOnScreenDebugMessage(1111, 3.0f, FColor::Green, "Carryable Base: Setting widget name vicinity based");
            }
            else
            {
                WidgetComponent->bDisplayElement(EWidgetElementOptions::WEO_TextField1, true);
                WidgetComponent->UpdateTextField(EWidgetElementOptions::WEO_TextField1, GetName());
                GEngine->AddOnScreenDebugMessage(2222, 3.0f, FColor::Green, "Carryable Base: Setting widget name");
            }
        }
    }

The above code shows a few functions i have on the widgetcomponent to update the widget itself, these get run but the widget does not update.

Oddly enough if i add


WidgetComponent->GetUserWidgetObject()->AddToViewport();

The text does immediately update the values and works correctly, however this now adds the widget to both the actor and the player viewport in the screen centre. (2 in the image below)

issue.jpg
Is there a way to get the same functionality without the widget being added to the viewport?

I figured this out, long story short it was some poor constructor logic. Basically it was running and setting the visibility of the widget in NativeConstruct() method of the widget. This was being called after the code snippet above (it takes a bit of time for all the UI stuff to be setup) and was hiding the elements again. Removing the code that set the visibility in the NativeConstruct() method sorted this issue.