UE4 Replicated variable doesn't reflect at server

MyCharacter.h

UPROPERTY(Replicated, EditDefaultsOnly)
float Health;

MyCharacter.cpp

float AMyCharacter::TakeDamage(float Damage, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
    Health -= Damage;
    return Damage;
}

When i start my game and call TakeDamage from server, then It’s working well. But if i call TakeDamage from client, it doesn’t reflect Health at server. So i tried to make RPC function MulticastRPCTakeDamage(float Damage) and replace Health -= Damage.

float AMyCharacter::TakeDamage(float Damage, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
    MulticastRPCTakeDamage(Damage);
    return Damage;
}

I also tried ServerRPCTakeDamage and ClientRPCTakeDamage. But it’s not working well. Help me!

Replication only works Server to Client. Any client to server communication needs to be done through an RPC directly from the client to the server, and you can’t multicast it (as multicast is when the server sends to all clients, calling it from the client doesn’t make sense).

The reason your code doesnt work even with a direct RPC is as follows: Only actors the client owns are allowed to send an RPC for the server. If you attack another character and call an RPC on that character to deal damage to itself, it won’t work at all because your client doesnt own that character. Examples of actors that a client owns are your PlayerController and PlayerPawn (parent of character). So, what you should do is when you attack a character, call an “attack” RPC on your own character which sends the attack to the server without leaving your character. Then on the server, apply the attack by calling the damage function on the other character.

Then your characters can replicate your health change to all clients if Health is set to being replicated. You left out a key part of replicating the health variable, you need to implement something like this to finish setting up your health to be replicated if you haven’t already:

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

It’s kind of difficult to wrap your head around first but the reason it’s like this is security and anticheat, if any client could rpc to any pawn then cheats could remotely control other players! Though i do wish there was a toggle for setting certain actors to allow rpcs from all clients.

I’m already did setting GetLifetimeReplicatedProps. And i also tried ServerRPC not only MulticastRPC. After read your answer, I tried to make attack function RPC. But i think i don’t understand your advice well so it’s failed. Can you explain again with simple source code please. By the way, It is my project git link : GitHub - kjinwoo12/UE4Study-NetworkFPS: Network FPS game using EU4.. I think it’s helpful for you understand my situation. Thanks for your help.

Did you check whether the client trying to send the rpc owns the actor it’s sending on? You can only send the rpc on an actor thats owned by the client. So if you call an RPC on the other actor it won’t work.