UUserWidget and progress bar in multiplayer

I’m trying to implement a classic Health bar in a gameplay UI. I got it working on the server but not on the client. In the UUserWidget the Health percentage is updated like supposed but not the Health bar. I tried a lot of things and I also tried in blueprint with the same result.
This is my cpp UUserWidget code (the function is called by the player controller and the log report the good percentage for both server and client)

#include "PuzzlePlatform/UI/GameplayUI.h"
#include "Components/ProgressBar.h"

void UGameplayUI::UpdateProgressBar(float HealthPercentage)
{
	if (HealthBar)
	{
		UE_LOG(LogTemp, Warning, TEXT("GameplayUI UpdateProgressBar Health Percent %f"), HealthPercentage);		
		HealthBar->SetPercent(HealthPercentage);		
	}
}


I tried to replicate the variable or not and I tried to directly pass the Health percentage to the UI but I got always the same result the variable is updated but not the Progress Bar. This is not the first time I created multiplayer UI but the first I use progress bar in multiplayer maybe it is different than other widget object. Thanks for your help!

How are you validating that the variable in the Widget is actually getting updated? How do you know this is true for the client?

I use print string in the blueprint version of the widget and it print on the screen the client number and the variable at each time the update is called. The server call the client function so I was thinking this is the good way too do. In c++ I use HasAuthority to set the variable on the server and the health percentage too then I call the client function with the server by passing the percentage in parameter.

Yesterday I rebuild the same code in a new project and I got it working the first time I don’t really understand what can I have done wrong in this version. I still have some difficulties with the subtleties of multiplayer programming.

It may have nothing to do with multiplayer. Could it just be the way the progress bar is hooked up? Do you have multiple. Try just setting that value to increase each frame locally and see if that’s the issue.

I created a local function on tick updating the health bar and reset to 0 when at 100% and it worked for both client and server.

I will give it a try again today to make it work in c++

I finally got it working . In blueprint I called directly the Controller Interface after setting up the variable and it work well but in cpp, I had to add another client function and call it from the OnTakeDamage Event.
This was the working blueprint version:

Summary

The BP_Character


The BP_PlayerController:

And finally the WBP_GameplayUI:
image

And this is the code needed in cpp to make it work:

Summary

The Character with one more function calling the interface on the client:

void AMyCharacter::TakeDamage(AActor* DamagedActor, float Damage, const UDamageType* DamageType, AController* InstigatedBy, AActor* DamageCauser)
{
	if (HasAuthority())
	{
		Health = FMath::Clamp(Health - Damage, 0.f, MaxHealth);
		HealthPercent = Health / MaxHealth;
		Client_UpdateHealthUI(HealthPercent);
	}
}

void AMyCharacter::Client_UpdateHealthUI_Implementation(float HealthPercentage)
{
	if (PlayerControllerInt)
	{
		PlayerControllerInt->UpdateHealthUI(HealthPercentage);
	}
}

The PlayerController(maybe i have a useless call to the client here but I did not test to call directly the Widget for now :

void AMyPlayerController::UpdateHealthUI(float HealthPercentage)
{
		Client_UpdateHealthUI(HealthPercentage);
}

void AMyPlayerController::Client_UpdateHealthUI_Implementation(float HealthPercentage)
{
	if (CreatedGameplayWidget)
	{		
		CreatedGameplayWidget->UIUpdateHealthBar(HealthPercentage);
	}
}

And finally the widget:

void UGameplayUI::UIUpdateHealthBar(float HealthPercentage)
{
	if (HealthBar)
	{			
		HealthBar->SetPercent(HealthPercentage);
	}
}

Thanks Sam for your support! This community is always a source of motivation!