How to Update TextRenderComponent for Client? (Networking)

Hello again guys,

I have a “Health” variable and my actor has a “HealthRender” component.
I think I successfully replicated the Health variable but the HealthRender just won’t update for the client.
Everything works perfectly on the server.

Here’s my code:

Update Health Functions

// Update the health variable
void ARPGTestCharacter::UpdateHealth(const float actualDamage)
{	
	if (Role < ROLE_Authority)
	{
		ServerUpdateHealth(actualDamage);		
	}
	else if (Role == ROLE_Authority)
	{
		Health -= actualDamage;
		HealthRender->SetText(FString::SanitizeFloat(GetHealth()));
		GEngine->AddOnScreenDebugMessage(5, 5.f, FColor::Red, "Damage Taken");
		GEngine->AddOnScreenDebugMessage(5, 5.f, FColor::Red, FString::SanitizeFloat(GetHealth()));
	}
}

bool ARPGTestCharacter::ServerUpdateHealth_Validate(const float actualDamage)
{
	return true;
}

void ARPGTestCharacter::ServerUpdateHealth_Implementation(const float actualDamage)
{
	UpdateHealth(actualDamage);
}

Replicating the Variables

void ARPGTestCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
	DOREPLIFETIME(ARPGTestCharacter, Health);
	DOREPLIFETIME(ARPGTestCharacter, HealthRender);
}

HealthRender in the Actor Constructor

ARPGTestCharacter::ARPGTestCharacter(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	bReplicates = true;
	bReplicateMovement = true;

	MaxHealth = 100;
	Health = 100;


	HealthRender = ObjectInitializer.CreateDefaultSubobject<UTextRenderComponent>(this, TEXT("Health"));
	HealthRender->AttachTo(RootComponent);
	HealthRender->SetText(FString::SanitizeFloat(Health));
	HealthRender->SetRelativeRotation(FRotator(90, -179.999496, 0));
	HealthRender->SetRelativeLocation(FVector(-20.000328, -79.999916, 60));
	HealthRender->SetIsReplicated(true);
	HealthRender->TextRenderColor = FColor::Red;

[...] }

Relevant Header Information

   	UPROPERTY(Replicated)
	float Health;

	UPROPERTY(Replicated)
	class UTextRenderComponent* HealthRender;
     

        // UpdateHealth Function
	void UpdateHealth(const float actualDamage);
	UFUNCTION(Reliable, Server, WithValidation)
	void ServerUpdateHealth(const float actualDamage);
	virtual bool ServerUpdateHealth_Validate(const float actualDamage);
	virtual void ServerUpdateHealth_Implementation(const float actualDamage);

A picture of what it looks like for Server / Client.
I want the client to see the HealthRender changes like the server does.

[Link because it’s small][2]
The problem is that HealthRender values are updated for the server but not the client (the health values stay at 100 for the client)

Thanks for your time and help.

I guess you need to remove the second if condition (Role == ROLE_Authority) because otherwise the

HealthRender->SetText(FString::SanitizeFloat(GetHealth()));

Will never get called by the client. The server will update the variable for all, because it is replicated, but the SetText will only get called on the server and not on the client.

Nope, still doesn’t work. Behaviour is the same.

What does a DebugMessage say on the client? Is the variable replicated correctly?

Yes, it prints the correct health values on both the client and the server :confused: that’s what makes it even more confusing for me.

Edit: If I call HealthRender->SetText(FString::SanitizeFloat(GetHealth())); in the Tick function of the actor, it works. Unfortunately I don’t really know why it didn’t work before.
Does anybody know?

Updating the TextRender every Tick, even when no changes occur, seems a little unnecessary.