UMG Text Widget binds not updating

Hi all,

I’ve been trying to figure out what’s wrong with my HUD. All of my text widget bindings don’t properly update. If I set them manually, they update fine, but not the bindings.

As an example, heres a Wave Counter in the top left of my hud.


As you can see, I created a variable within my hud called “CurWave”. I binded my WaveCounter text widget to this variable. I even set the default value to something weird so you can see it properly updates on the HUD’s construction, but won’t update after that

Wave 0

Wave 2 (You can see the print string, but the Text widget does not update)

This also leads me to another question. Should I use binds for something like this, or should I just manually set them (Ex: On Wave Start, Set Text Widget to current Wave)?

UE5.2

1 Like

Sounds like your event dispatcher doesn’t trigger am I correct? Does your “print string” node gets triggered? If it does then it means, your parameter values are incorrect. If not, then your event dispatcher does not get executed

Both the event dispatcher values and the string work. If you look at Picture 2, you can see that the dispatcher is hooked up into “CurWave” and CurWave is then hooked into the print string. You can also see CurWave being printed in screenshot 4.

I see, you didn’t set the text. You only set the value but you didn’t assign it to the text. Simply get the reference of the text and use the function “Set Text” targetted from the text component.

Well I believe the text should be changing because it’s binded. If you look at screenshot 1, you can see that the WaveCount text component has a text binding to CurWave.

It’s not a bug and I’ve been dealt the same thing with no problem at all, if it’s a bug then everyone will complain about it.

You might have set the variable somewhere else too. Again, give my method a try, you won’t lose anything and the setup won’t affect the tick. Use the “set Text” function node for setting the text box component. Make sure you unbind the variable to do this.

I’m not saying it’s a bug. I’m trying to understand how binds work because I can’t get them to work here. I can set the text just fine, I’m just trying to figure out why binding doesn’t work in this regard.

Can you double check this:

Its the same as the pic you posted

This should work just fine. If it does not, there is something about the project we do not know about. Not sure what to ask.


How certain are you this print string originates from the widget?

  • if you run the debugger for this widget, do you actually see the execution fire:

  • is this variable updated anywhere else? search for it across the project, not just this blueprint

I am 100% certain that the print string is from the widget. I have changed the print string to show you. I’ve been working on this HUD a bit so I made a seperate text widget with the text "Test: " next to it for debugging purposes. I recorded the event firing but unfortunately the bind still does not update the Text block widget. Also, I only made the variable “CurWave” for debugging purposes so I know that isn’t being set or changed elsewhere (I also rightclicked->Show references so you can see as well).




(Should say “Test: 2” after the wave ends, but still says “Test: 1”. You can see the PrintString print the correct value of CurWave, but the Bind does not reflect the update)

The only other information I think I can really offer at this point is that this HUD widget is derived from a C++ class. I update 90% of the HUD elements at this point using delegates.

HaloHUDWidget.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Components/TextBlock.h"
#include "HaloHUDWidget.generated.h"


class UListView;
class UTextBlock;
class UHealthComponent;
class AHaloFloodFanGame01Character;
/**
 * 
 */
UCLASS()
class HALOFLOODFANGAME01_API UHaloHUDWidget : public UUserWidget
{
	GENERATED_BODY()

	virtual void NativeConstruct() override;

	virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;

public:
	UFUNCTION(BlueprintNativeEvent)
	void SetHealth(float CurrentHealth, float MaxHealth);

	UFUNCTION(BlueprintNativeEvent)
	void SetShields(float CurrentShields, float MaxShields);

	UFUNCTION(BlueprintNativeEvent)
	void SetCanInteract(bool CanInteract);

	UFUNCTION()
	void SetInteractInfo(FText InfoText, UTexture2D* Icon = nullptr);

	UFUNCTION(BlueprintNativeEvent)
	void SetFragCounter(int32 NewFragCount);

	UFUNCTION(BlueprintNativeEvent)
	void SetPlasmaCounter(int32 NewPlasmaCount);

	UFUNCTION(BlueprintNativeEvent)
	void SetSpikeCounter(int32 NewSpikeCount);

	UFUNCTION(BlueprintNativeEvent)
	void SetIncenCounter(int32 NewIncenCount);

	UFUNCTION(BlueprintNativeEvent)
	void SetCompassDirection(float Yaw);

	

	UFUNCTION(BlueprintNativeEvent)
	void ConstructAmmoGrid(AGunBase* Gun);

	UFUNCTION(BlueprintNativeEvent)
	void SetAmmoReserveCounter(int32 AmmoReserve);

	UFUNCTION()
	void UpdateHUDMagazineElements(); //Maybe clean this up later

	UFUNCTION(BlueprintNativeEvent)
	void SetMagazineReserveCounter(int32 MagazineCount);

	UFUNCTION(BlueprintNativeEvent)
	void SetAmmoGridBullets(int32 CurMagazine, int32 MaxMagazine);
	
	void SetCrosshairType(int type);

	void SetCrosshairTexture(UTexture2D* NewTexture);

	UFUNCTION(BlueprintCallable)
	void SetFragHUDEnabled(bool bDisplay);

	UFUNCTION(BlueprintCallable)
	void SetWeaponHUDEnabled(bool bDisplay);

	UFUNCTION(BlueprintCallable)
	void OnHealthUpdated(UHealthComponent* HealthComp);

	UFUNCTION()
	void UpdateHUDWeaponData(AGunBase* EquippedGun, AGunBase* HolsteredGun);


	void Test();
	UFUNCTION()
	void UpdateSetAndWaveCount(int Set, int Wave);

	UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
	void PushTextNotification(const FText& Text);
	
	virtual bool Initialize() override;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	UTextBlock* WaveCount;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	UTextBlock* SetCount;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	UWidget* WeaponHUD;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	UWidget* FragHUD;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	UWidget* HealthHUD;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	UWidget* CompassHUD;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	UListView* TextNotificationList;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UImage* Crosshair;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UProgressBar* HealthBar;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UTextBlock* HealthNum;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UProgressBar* ShieldBar;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UTextBlock* ShieldNum;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UVerticalBox* InteractBoxWidget;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UTextBlock* InteractActionWidget;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UUniformGridPanel* AmmoGrid;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UTextBlock* FragCounter;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UTextBlock* PlasmaCounter;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UTextBlock* SpikeCounter;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UTextBlock* IncenCounter;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UTextBlock* AmmoReserveCounter;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UTextBlock* MagazineCounter;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TSubclassOf<class UUserWidget> AmmoGridChildClass;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UImage* EquippedGunWidget;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UImage* HolsteredGunWidget;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UImage* Compass;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UTextBlock* CompassNum;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	class UImage* InteractIcon;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float CompassDirection;

	TArray<UUserWidget*> BulletIcons;

	UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Colors")
	FLinearColor EnemyColor = FColor(255, 25, 25, 255);

	UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Colors")
	FLinearColor AllyColor = FColor(25, 255, 25, 255);

	UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Colors")
	FLinearColor InteractableColor = FColor(25, 25, 255, 255);

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Colors")
	FLinearColor HUDColor = FColor(255, 150, 50, 255);

	UPROPERTY()
	class AHaloFloodFanGame01Character* PlayerCharacter;
};

HaloHUDWidget.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "HaloHUDWidget.h"

#include "Blueprint/WidgetTree.h"
#include "Components/CanvasPanelSlot.h"
#include "Components/GridPanel.h"
#include "Components/UniformGridPanel.h"
#include "Components/Image.h"
#include "GunBase.h"
#include "HealthComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/ProgressBar.h"
#include "Components/TextBlock.h"
#include "Components/UniformGridSlot.h"
#include "Components/VerticalBox.h"
#include "HaloFloodFanGame01/HaloFloodFanGame01Character.h"
#include "HaloFloodFanGame01/HaloFloodFanGame01GameMode.h"

void UHaloHUDWidget::NativeConstruct()
{
	Super::NativeConstruct();
	UE_LOG(LogTemp, Warning, TEXT("Found Weapon"));
	SetFragCounter(PlayerCharacter->FragCount);
	SetPlasmaCounter(PlayerCharacter->PlasmaCount);
	SetSpikeCounter(PlayerCharacter->SpikeCount);
	SetIncenCounter(PlayerCharacter->IncenCount);
	if (PlayerCharacter->EquippedWep)
	{
		UE_LOG(LogTemp, Warning, TEXT("Found Weapon"));
		UpdateHUDWeaponData(PlayerCharacter->EquippedWep, PlayerCharacter->HolsteredWeapon);
	}
	PlayerCharacter->WeaponsUpdated.AddDynamic(this, &UHaloHUDWidget::UpdateHUDWeaponData);
	PlayerCharacter->GetHealthComponent()->OnHealthUpdate.AddDynamic(this, &UHaloHUDWidget::OnHealthUpdated);
	Cast<AHaloFloodFanGame01GameMode>(UGameplayStatics::GetGameMode(GetWorld()))->OnWaveStart.AddDynamic(this, &UHaloHUDWidget::UpdateSetAndWaveCount);
}

void UHaloHUDWidget::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
	Super::NativeTick(MyGeometry, InDeltaTime);

	FHitResult PlayerAim = PlayerCharacter->GetPlayerAim();
	if (Cast<IDamageableInterface>(PlayerAim.GetActor()) && PlayerAim.Distance <= 2000)
	{
		SetCrosshairType(4);
	} else if (Cast<IInteractableInterface>(PlayerAim.GetActor()) && PlayerAim.Distance <= 500)
	{
		SetCrosshairType(2);
	} else
	{
		SetCrosshairType(1);
	}

	SetCompassDirection(PlayerCharacter->GetFirstPersonCameraComponent()->GetComponentRotation().Yaw);

	//if (PlayerCharacter && PlayerCharacter->EquippedWep && PlayerCharacter->EquippedWep->CrosshairTexture) Crosshair->SetBrushFromTexture(PlayerCharacter->EquippedWep->CrosshairTexture);
	SetFragCounter(PlayerCharacter->FragCount);
	IInteractableInterface* IntActor = Cast<IInteractableInterface>(PlayerAim.GetActor());
	if (PlayerAim.bBlockingHit && IsValid(PlayerAim.GetActor()) && IntActor)
	{
		FText IntText;
		UTexture2D* IntIcon;
		IntActor->Execute_GetInteractInfo(PlayerAim.GetActor(), IntText, IntIcon);
		SetInteractInfo(IntText, IntIcon);
		SetCanInteract(true);
	}
	else 
		SetCanInteract(false);
}

void UHaloHUDWidget::SetInteractInfo(FText InfoText, UTexture2D* Icon)
{
	if (Icon)
	{
		InteractIcon->SetBrushFromTexture(Icon);
		InteractIcon->SetVisibility(ESlateVisibility::Visible);
	}
	else
	{
		InteractIcon->SetVisibility(ESlateVisibility::Hidden);
	}
}


void UHaloHUDWidget::SetCompassDirection_Implementation(float Yaw)
{
	CompassDirection = (Yaw+180);
	float Offset = 45;
	float x = ((Yaw+Offset)*-10);
	UCanvasPanelSlot* CanvasSlot = Cast<UCanvasPanelSlot>(Compass->Slot);
	CanvasSlot->SetPosition(FVector2d(x, 0));
	//UE_LOG(LogTemp, Warning, TEXT("%f"), Yaw);
	CompassNum->SetText(FText::AsNumber(x));
}


void UHaloHUDWidget::ConstructAmmoGrid_Implementation(AGunBase* Gun)
{
	if (!Gun->BulletWidget) return;
    AmmoGrid->ClearChildren();
	BulletIcons.Empty();
	int32 Columns = 15;
	
	for (int i = Columns; i > 0; i--)
	{
		if ((Gun->MaxMagazine)%i==0)
		{
			Columns = i;
			break;
		}
	}
	int32 Rows = Gun->MaxMagazine/Columns;
	int CurBullet = 0;
	for (int i = 0; i < Rows; ++i)
	{
		for (int j = 0; j < Columns; ++j)
		{
			UUserWidget* BulletIcon = WidgetTree->ConstructWidget<UUserWidget>(Gun->BulletWidget);
			UUniformGridSlot* UniSlot = AmmoGrid->AddChildToUniformGrid(BulletIcon, i, j);
			UniSlot->SetHorizontalAlignment(EHorizontalAlignment::HAlign_Fill);
			UniSlot->SetVerticalAlignment(EVerticalAlignment::VAlign_Fill);
			BulletIcons.Add(BulletIcon);
			CurBullet++;
		}
	}
}

void UHaloHUDWidget::SetAmmoReserveCounter_Implementation(int32 AmmoReserve)
{
	AmmoReserveCounter->SetText(FText::AsNumber(AmmoReserve));
}

void UHaloHUDWidget::SetAmmoGridBullets_Implementation(int32 CurMagazine, int32 MaxMagazine)
{
	int i = 0;
	for (auto BulletIcon : BulletIcons)
	{
		if (i < CurMagazine)
			BulletIcon->SetColorAndOpacity(HUDColor-FLinearColor(0,0,0,.5));
		else
			BulletIcon->SetColorAndOpacity(FLinearColor(0,0,0, .25));
		i++;
	}
}

void UHaloHUDWidget::SetMagazineReserveCounter_Implementation(int32 MagazineCount)
{
	MagazineCounter->SetText(FText::AsNumber(MagazineCount));
}


void UHaloHUDWidget::UpdateHUDMagazineElements()
{
	SetMagazineReserveCounter(PlayerCharacter->EquippedWep->CurMagazine);
	SetAmmoReserveCounter(PlayerCharacter->EquippedWep->CurReserve);
	SetAmmoGridBullets(PlayerCharacter->EquippedWep->CurMagazine, PlayerCharacter->EquippedWep->MaxMagazine);
}

void UHaloHUDWidget::SetCrosshairType(int type)
{
	switch (type)
	{
	default:
	case 1:
		Crosshair->SetColorAndOpacity(HUDColor);
		break;
	case 2:
		Crosshair->SetColorAndOpacity(InteractableColor);
		break;
	case 3:
		Crosshair->SetColorAndOpacity(AllyColor);
		break;
	case 4:
		Crosshair->SetColorAndOpacity(EnemyColor);
		break;
	}
}

void UHaloHUDWidget::SetCrosshairTexture(UTexture2D* NewTexture)
{
	Crosshair->SetBrushFromTexture(NewTexture);
}

void UHaloHUDWidget::SetFragHUDEnabled(bool bDisplay)
{
	if (bDisplay)
	{
		FragHUD->SetVisibility(ESlateVisibility::Visible);
	} else
	{
		FragHUD->SetVisibility(ESlateVisibility::Hidden);
	}
}

void UHaloHUDWidget::SetWeaponHUDEnabled(bool bDisplay)
{
	if (bDisplay)
	{
		WeaponHUD->SetVisibility(ESlateVisibility::Visible);
	} else
	{
		WeaponHUD->SetVisibility(ESlateVisibility::Hidden);
	}
}

void UHaloHUDWidget::OnHealthUpdated(UHealthComponent* HealthComp)
{
	SetHealth(HealthComp->GetHealth(), HealthComp->GetMaxHealth());
	SetShields(HealthComp->GetShields(), HealthComp->GetMaxShields());
}

void UHaloHUDWidget::UpdateHUDWeaponData(AGunBase* EquippedGun, AGunBase* HolsteredGun)
{
	if (EquippedGun)
	{
		SetCrosshairTexture(EquippedGun->CrosshairTexture);
		MagazineCounter->SetVisibility(ESlateVisibility::Visible);
		AmmoReserveCounter->SetVisibility(ESlateVisibility::Visible);
		AmmoGrid->SetVisibility(ESlateVisibility::Visible);
		SetAmmoReserveCounter(EquippedGun->CurReserve);
		EquippedGunWidget->SetBrushFromTexture(EquippedGun->WeaponIcon);
		ConstructAmmoGrid(EquippedGun);
		UpdateHUDMagazineElements();
		EquippedGun->OnFire.AddUniqueDynamic(this, &UHaloHUDWidget::UpdateHUDMagazineElements);
		EquippedGun->OnReload.AddUniqueDynamic(this, &UHaloHUDWidget::UpdateHUDMagazineElements);
	} else
	{
		MagazineCounter->SetVisibility(ESlateVisibility::Hidden);
		AmmoGrid->SetVisibility(ESlateVisibility::Hidden);
		AmmoReserveCounter->SetVisibility(ESlateVisibility::Hidden);
	}
	if (HolsteredGun)
	{
		HolsteredGunWidget->SetVisibility(ESlateVisibility::Visible);
		HolsteredGunWidget->SetBrushFromTexture(HolsteredGun->WeaponIcon);
	} else
	{
		HolsteredGunWidget->SetVisibility(ESlateVisibility::Hidden);
	}
}

void UHaloHUDWidget::UpdateSetAndWaveCount(int Set, int Wave)
{
	SetCount->SetText(FText::AsNumber(Set));
	WaveCount->SetText(FText::AsNumber(Wave));
}

void UHaloHUDWidget::PushTextNotification_Implementation(const FText& Text)
{
	UE_LOG(LogTemp, Warning, TEXT("Pushing notif"));
}


bool UHaloHUDWidget::Initialize()
{
	Super::Initialize();
	
	
	return true;
}

void UHaloHUDWidget::SetHealth_Implementation(float CurrentHealth, float MaxHealth)
{
	if (HealthBar) {
		HealthBar->SetPercent(CurrentHealth / MaxHealth);
		HealthNum->SetText(FText::AsNumber(CurrentHealth));
	}
}

void UHaloHUDWidget::SetShields_Implementation(float CurrentShields, float MaxShields)
{
	if (ShieldBar) {
		ShieldBar->SetPercent(CurrentShields / MaxShields);
		ShieldNum->SetText(FText::AsNumber(CurrentShields));
	}
}



void UHaloHUDWidget::SetCanInteract_Implementation(bool CanInteract)
{
	if (CanInteract)
		InteractBoxWidget->SetVisibility(ESlateVisibility::Visible);
	else
		InteractBoxWidget->SetVisibility(ESlateVisibility::Hidden);
}
void UHaloHUDWidget::SetFragCounter_Implementation(int32 NewFragCount)
{
	if (FragCounter)
		FragCounter->SetText(FText::AsNumber(NewFragCount));
}

void UHaloHUDWidget::SetPlasmaCounter_Implementation(int32 NewPlasmaCount)
{
	if (PlasmaCounter)
		PlasmaCounter->SetText(FText::AsNumber(NewPlasmaCount));
}

void UHaloHUDWidget::SetSpikeCounter_Implementation(int32 NewSpikeCount)
{
	if (SpikeCounter)
		SpikeCounter->SetText(FText::AsNumber(NewSpikeCount));
}

void UHaloHUDWidget::SetIncenCounter_Implementation(int32 NewIncenCount)
{
	if (IncenCounter)
		IncenCounter->SetText(FText::AsNumber(NewIncenCount));
}

It’s been a while and I dont remember all of my problems here as I solved most of them by now, but I figured out that text widgets don’t really like being updated in Tick which caused a lot of issues. I’ve moved away from updating most text widgets from bindings and tick and instead to dispatchers. The one I couldnt really avoid, the compass number, stumped me for a while, but I found that turning on “Simple text mode” caused it to start working properly. Perhaps this will assist someone in the future.

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.