Networking: Notify value changed on ALL connected members

In my Networked game I am using a listen server (not dedicated) to maintain a connection between multiple instances of my game.

In my PlayerState class I have the following field:

	UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Health)
	float Health;

My OnRep_Health function is working correctly and calls a delegate to update the UI on clients. However, because replication doesn’t happen on the server side that means that the player who is running the server will not receive these events correctly. This won’t work!

One solution I see now is to just have a NetMulticast setter function for Health like this:

	UFUNCTION(NetMulticast, Reliable)
	void SetHealth(float InHealth);

However I’m a little skeptical of this solution. Won’t the combination of NetMulticast and Reliable have a significant performance dip compared to OnRep? Does anyone have insight on whether this is a bad idea or not?

Repnotifies should work on a listen server but if not, just create a function UpdateHealth, put this in your OnRep for clients and just call it when health changes on the server

1 Like

After doing some digging you’re half right RepNotifies do call on the server if you’re using blueprints. However in C++ code it doesn’t, which IMO makes sense since the value is never actually being “replicated” on the server, just set. If this isn’t actually the case let me know, it’d be extremely convenient for me haha.

I went partially into creating an UpdateHealth like you’re saying, but it’s a little painful that I have to call it every time health changes on the server. Because of this someone else could easily introduce a bug if they don’t call the function.

I kept looking and found how Epic handles this type of thing, if you look at APlayerState you’ll find private FString PlayerName which is replicated by OnRep_PlayerName and handled by GetPlayerName and SetPlayerName. The setter itself checks if it’s a server, and if so calls the OnRep funciton manually. It’s a little extra code but I’m thinking that’s my plan.

Here’s the implementation:

void AUnderlordPlayerState::SetHealth(const float NewHealth)
{
	Health = NewHealth;
	
	ENetMode NetMode = GetNetMode();
	if (NetMode == NM_Standalone || NetMode == NM_ListenServer)
	{
		OnRep_Health();
	}
}

technically you should only be updating health on server anyway so you could lose the server checks and always call OnRep.

so really you shouldnt have to worry about bugs, server always sets and updates and client receives notifies.

it is strange how BP is different though