Download

Replication - Getting the Server to Destroy an Actor for the Client

Hi everyone. I’ve decided it was about time I learnt about replication. I’ve watched the tutorials by epic and done some reading on replication. I feel like I understand how it works but I cant seem to be struggling to get something as simple as destroying an actor to work.

I know that what I need to do is ask the server to destroy the actor for the client. This is the setup I have at the moment. I’m at a complete lose as to why it’s not working and feel like I’m completely missing something.

At the moment it only seems to do something when the server does anything.

The following nodes are in my Pawn class. Any help as to where I’m going wrong would be greatly appreciated.

&stc=1

Sorry for the double post but I finally figured it out.

It turns out that when it’s runs the functions on the server it also uses the servers variables. This means that the variable would most likely be empty unless the server was looking at something. A simple fix was to pass the variable through the function so it can be used when it comes out of the event to the server. :slight_smile: Hopefully this will help someone else.

It does help, ty!!!

Are you using linetrace to set looking at actor?

you should set the “Switch has Authority” node before anything that spawns

Hey there, while this might work, it’s not a good practice.

The better way would be telling the Server to destroy the Actor which MIGHT be where the Clients say it is.

So for example, on E press, call a RunOnServer Event that does a LineTrace. So the Server does the Trace and with this you can be sure
that the Client is not cheating.

The way you do it, everyone could just tell the Server to destroy what ever you have in the Variable and is also replicated. For example another Player.

You should only register Input on the Client and share visual stuff (health in the UI etc), but never actually let a Client decide what is going to happen.

In addition to UE4s Tutorials about Networking, I recently released a 100+ Pages strong PDF file (for free) about Multiplayer in UE4: http://cedric.bnslv.de/unreal-engine-4-network-compendium-released/

Don’t know if I’m understanding/reading this the right way but shouldn’t the “Visual” line trace be done on the client?

http://www.tomlooman.com/tutorial-multiplayer-supported-usableactor-system-in-blueprint/ Tom also does the trace on the client side? the object itself is replicated as well so it’s already handled by the server?

The OP asked this question over a year ago lol.

Listen to @eXi though, he knows, he knows… :stuck_out_tongue:

The latest post by eXi himself was (06-19-2016, 10:14 PM) yesterday? I’m just asking as this topic was still on going and I’m having a hard time with item pickups in multiplayer. Even after going through 100 pages of eXi i still can’t get the pickup to replicate the right way.

Well, even if Tom lets the Client do it, I wouldn’t. Or I would, at least, have a second check somewhere.

Imaging you have 10 items in your Map that a Player can pickup. Your code lets the Client trace the Pickup and tell the Server “Hey, I want to pick up this item I found and passed you via a parameter”.

Now what could go wrong about that? The Pickup on the Client and on the Server don’t actually need to be at the same place. This means, the Client could simply cheat the Position of all 10 Pickups
right in front of him and then trace them. While all 10 Pickups are way off, hidden somewhere on the Server, the Client still can trace his deplaced Version and collect all 10 items.

BUT, if you let the Server do the Trace, the Client can have 100 Pickups cheated to his location, they are not in front of him on the Server, so the Server Trace WON’T hit them.

You could do the trace on both. If the Client hits an Object and the Server not, you could kick him, but I would just go straight for the Server trace and let him do all the Pickup logic.

Thanks for this/the explanation. I think I have a working pickup system now (multiplayer ready/working). I have a simple Flipbook character with a simple Overlap box to trace hits/pickups. Once it hits something I let the server set the hitactor/pickup [run on server]. I think call a [run on owning client] to handle the actual pickup that has bee validated/set by the server.

Could you have a look at the following screenshots to see if it’s about right? At least it’s working on server and client pickup now.

&stc=1

&stc=1

I assume the PlayerCharacter is set to replicate.

The “OnComponentBeginOverlap” will be called on SERVER and CLIENT anyway. Both instances will overlap, so both will call the event.
So you don’t need the “RunOnServer”. You just need to filter the client with “SwitchHasAuthority” and using the “Authority” exec.

Then you don’t need the Sweep Result, nor do you need the RunOnServer event, so you can directly use the “OtherActor” input, cast it and save it.

Calling “AddToInventory” on the Client seems a bit weird. The Inventory should be replicated and the adding should only happen on the Server.

NO LOGIC ON CLIENTS! :smiley:

You only want to pass the Client a minimum of information, for example only the stuff he actually needs to display the items: Icon, Name, Description, StackCount or so.

The actual inventory should only exist on the Server!

Thanks for the answer, guess Ill have to dig in a bit more then.

############################

It’s still a bit hard for me to comprehend replication (hope I’m not the only one). The server should change the values but where should the server be changing them? Should this be on the Game Instance?

Well, it’s normal that Replication takes time to understand.

The GameInstance is not the right place, as it only exist once per Game. There is no replication going on. Every started Game has one GameInstance and non can access that despite the Game itself.

What values are we talking about? An Inventory might sit on the “PlayerState”. Why not on the Player itself? Well, if you kill/destroy the pawn, the Inventory is gone too. The PlayerState describes the State of each Player,
and is suited to (in C++ only atm) fill in Variables when a Client switches the Level or reconnects after a forced disconnect. So I would place the Inventory on the PlayerState.

And there, since the PlayerState is replicated, you can deal with setting Variables/Values on the ServerSide of it.

PS: A Network Inventory is one of the hardest things to do for a beginner. So I would try to do something easier, until you understood the framework etc.

Again thanks for taking the time to give some insight. The problem is I already have a working lobby/session system and do save values to the player state. I just have to look into how and where to save and get values and it seems the best option is to write it to the player state -> then directly save it into the character savegame.

Many thanks you have enlightened me quite a bit with a few simple and straight forward answers.

Would it be wise to do a pickup by the server with a multicast? It seems like the only way I can get it to work :frowning:

What exactly are you Multicasting?

Here is how I did my Networked Inventory:

  • Created Item Struct/Object/Actor (in C++ I would use a DataAsset) for the Items

  • Create a Component “InventoryComponent” in my PlayerState/PlayerController

  • Fill it will all SERVER SIDE ONLY logic about adding, removing, splitting, stacking, moving, etc Item in this ONE Inventory

  • The Inventory itself is an Array of the Struct/Object/Actor/DataAsset (what eve you use for it)

  • Create a second Component “InventoryManager” in my PlayerState/PlayerController

  • Fill it will all SERVER SIDE ONLY logic about handling TWO Inventories, for example moving Item A from Inventory ONE to Inventory TWO
    – So I have an actual Inventory, that deals with moving stuff inside of it and a Manager that deals with moving stuff between two Inventory Components

  • When a Client presses a Button, I do a RunOnServer Event (directly)

  • In this RunOnServer Event, I let the Server Version of my Pawn/Character do a LineTrace

  • When I hit an ItemActor, I get my InventoryComponent from my PlayerController/PlayerState and call “AddToInventory” for it
    – So this happens on ServerSide only

  • Now, instead of Replicating the Array, I created a “Multicast” Event in my InventoryComponent, which has a custom “InventoryStruct”, with only the minimum of information about
    an Item
    – I use this Struct to share Item Information from Server to Client. The Client doesn’t need the whole Inventory to be replicated, only some data that he uses to display the Item (Image, Name, Description, etc).

  • So, before calling the Multicast, I call a function that takes the current Array and fills the Struct Array with all the Data I need.
    – I do this by having a Function on the Item that fills the Struct and returns it. With this I can have different Items, that all deal with filling their unique information themselves

  • Then, for the Multicast, I pass the now filled Struct Array and on the Client Side, I call a function to update my UMG Widget and pass this function the new Struct Array.

  • It then updates the visual inventory with the needed data

PS: Why a Multicast if only the one Client sees his own Inventory? Because I had Chests in my Game that also had this Inventory. I could probably use a Child Component and rework some stuff,
but if you don’t set the Multicast to reliable, it’s working quite nice.

This is the result of the upper setup:

Hi and thanks, I think we have a similar setup for the inventory and crafting system. The multicast I call when the pickup is done. It seems to work for both client and server the main problem for me is having the pickup to work when calling an [run on server] event, it works on the server but not the client. I’m really sorry to hassle you about this and I did read your whole document as well as the tutorials from the unreal series about network/replication. The below images show my current “working” setup with a multi cast.

The Inventory itself get’s spawned on my Ingame_PlayerController at [Event_BeginPlay] (the ingame PlayerController is based on the Outgame Controller so I have a ingame controller for gameplay and a outgame controller for the main menus when starting the game and hosting a lobby or starting a single player session) and is an actor with: An int for the size of the inventory and a Item array based on a structure => (count(int) and class(r master item))

I know this is not a easy thing to do but I got the rest of what I need “gameplay” wise prototype already (player damage / ingame and outgame menus / lobby / hosting a server) I can have multiplayer walking around with animations replicated (flipbooks) and server/client can damage each other and use items to get their health back. I just have the feeling I’m missing something “simple” in the process. I learned the hard way not to use [get_player_controller] but use [get_controller] (it’s needed for the server to execute stuff for the client?)

&stc=1

&stc=1

&stc=1

&stc=1

&stc=1

&stc=1

Again thanks for taking the time to even reply to this topic I really appreciate it. As for your youtube link it looks neat and clean I like it very much.

Just looked at you’re pdf exi. Really nice man

you should have the begin overlap happening on the server then calling an event on owning client to tell the client it picked up the item. you have to pass the item through the event because the 2 events happen on different instances of the game, one the client and the other the server so in order for the client to know what item your referencing it needs to receive it in the event and the item needs to be set to replicate so its reference remains the same between clients

edit: I know this was 5 years ago but I believe its relevant for other people having the same problem