Client cannot call event on server

I have an item BP, a child of it, and a widget.
The player interacts with the child via BP interface.

When I run my game, the server behaves as expected on all clients. Items are destroyed when picked up, and spawned when dropped. However, when the client tries to interact with an item it does not destroy itself. The client can pick up the same item multiple times.

I used a print string for the RPC event. Client side, it seems like the “Server destroy item” is not called at all.

Any thoughts?



100% of all interaction should be happening on the server. Not on the client.

Client-side you should only be doing animations and input.

e.g.
Client interacts (trace or click event), gets a positive result → executes a montage/fx/sound etc → RPC’s server to interact.
Server interacts → gets a result → executes authoritative action.

I’m not sure I quite understand.

So, the player presses E to interact— via an interface, tells the item child to execute its parent event—the parent event executes on server, then on all clients.

So… I should call the interact event on the server.
Here’s what I’ve tried, but it still does not work.

Your original implementation did not work because you were attempting to call a server side function from the non-owning client version of your actor. As the items were spawned on the server (not the client) the server owns it. As such, any server RPC calls from the client version of the item will have no effect…it doesn’t own it. That’s a long way of saying what @Rev0verDrive said with their flow-graph :slight_smile:

Your latest iteration based off the advice of @Rev0verDrive looks to be correct. When you say “it still does not work” what do you mean, which part? Is it not adding the item? Or is it just not destroying the actor? One suggestion is that you do not need to call DestroyActor on all the clients. Destroying the actor on the server will automatically propagate to the clients. So try calling “DestroyActor” right off of “DestroyItem”.

That being said, the best way to trace the execution path is to simply put debug prints in. This will show you where the function is being called (server or client), and you can start to trace the execution path.

Client presses Interact…I’m assuming you do a line trace or such to determine if there is an interactable actor.

If the interaction returns “true” you RPC the server to interact in the same way. Check if there’s actually something there. IF you don’t then this enables players to “claim” interaction and force the server to do their bidding. This is Client Authority. Server should always be the authority.

Anyway, when the server interacts and gets a hit, IT calls the interaction event on the HIT actor.

Here’s a complete and thorough multiplayer interaction series.

1 Like

I get what you mean but I don’t quite understand what I’m supposed to do. I have to make sure that my actor is created not only on the client, but also on the server?

I’m a bit confused. Here’s what I want to do:
In my multiplayer game, players can pick up items and drop them. The player interact with the items using a line trace, and when picked up, the item is destroyed. The player can also drop the item. I do this by spawning an actor of that item’s class.

In my current setup, there are 2 items in the level. I assume they are owned by the server. A client can pick up (destroy) the item owned by the server, then the client can drop (spawn) the item which is now owned by… the client. I’m guessing this is the problem… but the client can’t even pick up an item so… idk

I used a print string to find the problem.


With this setup, when I play the game the print string outputs: “Server: Interact” regardless of who is interacting (client/server).

Now, the destroy item runs only on the server, but still it does not work.

Interact trace → Hit result… If it hits an item → RPC server to do the same trace.

Server does trace → Hit result… If it hits an item → “Spawn the actor → Attach it → Set Owner → Add to inventory”.

Item Actor needs to be set to “REPLICATES”.

The replication system will automatically replicate that actor to you and all other clients. Your client and SIMS on other clients will spawn the actor and attach it.


Dropping…

Input to drop → RPC SERVER!
Server Detaches, Updates Inventory → Drops and sets actor to Destroy.

BOOM!

Technically I do not need to make the server cast a line trace. The line trace only allows the player to press E to fire the interact event.

Player gets close to item->If line trace hits->Player can now interact
Player interacts with E->Tells the item child to fire the parent destroy item event.
Item parent then destroys the item.

I used a custom event which runs on server the interface interact call as you can see in the screenshot. This works when the server interacts, but when the client interacts it doesn’t.


This runs on my player blueprint, and if I put a print string after the interact call it works for both the server and the client.


The item child contains this code. When the Server calls the previous code in the player BP, the print string here in the item BP prints out “Interacted”. When the client does the same thing the print string shows nothing.

I’m sorry if the problem is obvious or I’m doing something wrong. I have never made a multiplayer game.

It works, but it 100% open to cheating. It’s 100% client authoritative.

UE is based on the Client-Server model in which the server is the authority.

So I did a little more testing and found out that the problem is somewhere else.


This current setup should work, regardless if it is 100% open to cheating.
Line trace hits->player interacts->adds item->tells server to destroy actor.

The target is coming from the hit result of the line trace: “Hit Actor”. When the client interacts the print string shows the correct name of the hit actor but it does not destroy it (also it gives the “Accessed none” error for the destroy actor node). When the server interacts the print string shows nothing, yet it destroys the correct actor.

Because the reference you are sending to the server as target is a local reference. It needs to be the actor in the servers sim.

Thus why the server has to do its own interaction.

It does work now, but there’s still a problem. The line trace that the server casts is not right. The client casts a line trace out of the camera in the forward direction up to 300 units. The server casts the line trace out of the client’s camera position in the CLIENT’s forward direction.

In other words, the player moves around its camera and the line trace always hits where the player points, but on server the line trace goes in front of the player parallel to the floor regardless of where the player points the camera.

As an example, if my item is cone shaped and the client aims on the lower edge, the server trace does not hit anything. But if the client aims in the center it might hit.


I’m not sure why this is happening. I’ve double checked that the players replicate their movement.

For server you need to use Camera Manager → get camera location
&& use Get Aim Rotation → Forward Vector

This is all covered in the vid I posted.

One more thing… Spawning the actors doesn’t really work.

When the player presses a button, my item should spawn on the server. I used some print strings and it seems that it runs fine. Still, when clients drop items, they are local. Not even the server can see them.

I’m assuming there something to do with the ownership of the spawned actor. I should set the owner to be the server, right? How do I get a reference to the server?

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.