RPC function vs RoleAuthority check?

OnPickup is a function that gets called when the Actor overlaps the Pickup Mesh. So OnPickup() should be called from the Client, I guess…

I sometimes use this structure in my code base when I don’t specifically care who calls the functions, but who may run the function. For example, if I know a function is going to be called on the server and the client then I may want to avoid an RPC (to save on traffic data).

A RPC function call would indeed achieve the same result, but if you can avoid having to do one; you might as well.

The problem now is that I don’t know why the pickup doesn’t work in my case.

Here is what happens, @eXi If the client picks up the item, the latter doesn’t disappear AND the DebugMessage appears only on the SERVER.

What’s going on?

Overlap functions are called on Client and Server. You need to limit it to the Server.
In the Overlap Function, make the Authority check to limit it to the Server. Then you don’t
even need the “OnPickup” function. You can directly call the Multicast in the Overlap function if you want.
Though you can also just call the Pickup and let that one call the Multicast. That’s up to your logic.

But you should just know that Overlap is called on Client and Server and you need to limit it to Client or Server
depending on what you want to do.

THOUGH: Because you have the “return” in there if a client calls it, you can call the function in the Overlap
without limiting it to the Server. The Client call will be caught in the Pickup function then.

So when you overlap, the Server and Client call OnPickup. The Client gets the return and the Server should call
the Multicast. The Multicast then is called on all replicated instances of that Actor (not on a second Pickup, just all
instances on the other Clients and Server).

So in fact, it should work the way you do it. Maybe the boolean is not true on all Clients? Is the Pickup actor replicated?
Otherwise you can’t call Multicasts on it.

I’ll be more specific

These are functions declared as UFUNCTION(Reliable, Client)
b9978f1a00f5732490e46fdad00e24852b0e477c.jpeg

When I pickup the health/armor, I expect to see that DebugMessage only on the player that took the pickup.
Instead, this happens:

Question: why?
@eXi

Is it possible to see a little more of the code?

Can we also get more of an understanding of the context?

I’ve learned never to trust debug messages to appear in the right places all the time.

Run in standalone, see what happens (uncheck UseSingleProcess in the advanced PIE drop-down menu).

Actually it seems to be a problem of DebugMessage which appear always everywhere.

Anyway, look at this code from ShooterGame

ab53518cd270d91996ccb14845e7d1da63f9cbbb.jpeg

If it’s not the client, call a ServerRPC function that executes on the server.

I really don’t understand why the developers didn’t just do:



if( Role < ROLE_Authority )
   return;

SetCurrentWeapon(Weapon, CurrentWeapon);


It’s possible that EqupWeapon is public and can be accessed from anywhere, but ServerEquipWeapon is private/protected. It is also possible that they just did this for simplicity. This way you can just call EquipWeapon on the client OR on the server and it will end up calling SetCurrentWeapon on the server either way.

So it’s just a matter of choise? My method would produce the same result?

The code from the ShooterGame is called on Server OR Client.

If EquipWeapon gets called, it checks if the one who called it is the Server or a Client.
If it’s the Server, we can directly equipped the Weapon via SetCurrentWeapon, if it’s the Client, we call the ServerRPC ServerEquipWeapon to get to the ServerSide
and then call EquipWeapon again, which will now end up in SetCurrentWeapon.

Your version would only work if the Server calls it. Clients wouldn’t be able to call that method.
That’s the difference. ShooterGames function can be called by the Client and will then be moved over to the Server.

Why? Because that’s how replication works. Only the Server can set Replicated Variables. If the Client would set the Weapon by itself,
no one would get the replication. That’s why he tells the Server to do that.

As explained above, NO, your method is not the same and will produce a different result.

You told me that each player in a Multiplayer game runs both the Server and the Client.

So when my EquipWeapon() function is called, both the client and the server will run into that…and I can easily block the client and make the server keep going through the function… or maybe not?

I told you, that if you use the BeginPlay or similar events, like EventTick etc, it will end up being called on all instances of that actor. So Client Versions and Server Version (if they exist).

If you call your EquipWeapon function in the BeginPlay etc, then yes, both will call it.

But imagine it’s just a MouseWheel that scrolls through weapons. The Client uses that one, so if he scrolls and selects a new weapon, the Client Call needs to be RPC’d to the Server.
But, if the ListenServer uses the MouseWheel, it will end up as a Server Call, since the ListenServer… is the Server.

This reply is very useful.

I’ll post here when I have issues.

@eXi



void AMyCharacter::PostInitializeComponents()
{
	Super::PostInitializeComponents();

	if (Role == ROLE_Authority)
	{
		Health = 100;
		Armor = 0;
		InitializeInventory();
	}
}


The code above tells the **server **to set the initial parameters for every player in the game.

Actually, the Health and the Armor are succeffully set.

But the InitializeInventory() function happens on the server and not on the client…



void AMyCharacter::InitializeInventory()
{	
	if (Role < ROLE_Authority)
		return;

	int32 NumWeaponClasses = DefaultInventory.Num();


	for (int32 i = 0; i < NumWeaponClasses; i++)
	{
	       ...
               // Spawns the weapons in the world and adds them to the player's inventory
               ...
	}
}


At the game start, I see the weapons spawned for the Server but not for the Client.

What’s happening?

Well yeah, you call the Inventory function on the Server. Are the Weapon Classes, that you spawn, set to replicate?

Ok I solved the previous problem, now look at this one that I’m sure it’s very stupid.

I’m spawning a default inventory for each player in the game, but only when the player picks up the Weapon from the ground, that Weapon will be **Enable()**d

Now when I set the **bEnabled **boolean to true in the Weapon class (for the local player in the game) it doesn’t work on the client, but works on the server.
OF COURSE, the function Enable() is called on the server

Any ideas?

It’s always the same idea: If you want to set something that is replicated from Server to Clients, you need to set a REPLICATED Variable on the Server.
And the Actor itself needs to be replicated as well.

Both the Weapon class and the bEnabled variable are already set to replicate!

Be sure that replication takes time. It’s not instant. You expect the Client to get the Updated Variable value directly after calling the RPC/Setting the Variable on the Server.
If you need to call something that needs the updated variable, either set it via an RPC on the Client too, or set it ALSO on the Client (+ the RPC), or use a REPNOTIFY variable.