How to Use Object with RunOnServer event?

Hey!

So I call the SpawnItemFromPlayer in the widget. In the SpawnItemFromPlayer event I checked and the ItemObject (Which is an Object that owns information about the item) is valid and everything is okay. So I call it from a client and the client event is a RunOnServer event. Here, the ItemObject gets invalid. Why will it be invalid here?
Here is the OnDrop function in the Widget.

Here is the SpawnItemFromPlayer event in the PlayerController.

Hi, where do you create the ItemObject? What you’re sending through the RunOnServer event is just a pointer, not the actual object itself. If it doesn’t exist on the server then the pointer will be invalid there.

Well it’s an object like that. So I created in the content browser.

329099-itemobject.png

And it gets the informations in the Base Actor Class of the items like that.

329100-itembase.png

Then I use this in the ItemBase with the TryAddItem, inside the overlap event.

329121-itembase2.png

Sorry I wasn’t clear. What I meant is to ask where (during the game) you spawn the ItemObject from which you sent a pointer/object reference to the server via the RunOnServer event. That spawning needs to happen on the server (otherwise the server won’t know about it) and the ItemObject needs to replicate (otherwise the client won’t know about it).

So that means that “GetDefaultItemObject” needs to happen on the server and the client would need to send a reference to that same ItemObject via the RunOnServer event to the server.

If you only locally spawn the ItemObject on the client and then send the pointer/object reference of it to the server, then on the server it will be invalid since the object that the pointer/object reference points to does not exist on the server.


So if you current setup is something like: client hits some button in UI → client spawns ItemObject → client sends RunOnServer Event to the server with the ItemObject, then it might be better to do

client hits some button in UI → client send RunOnServer Event → server handles the rest (spawns ItemObject and adds it to inventory, and replicates things that the client should know about)

Otherwise you could explain a bit more what you’re trying to do.

I tried to do the “GetDefaultItemObject” with a RunOnServer event and then that ItemObject gets invalid for the Clients. Does that mean it’s on the server but not on the client? What would be the correct way to do it?

And the ItemObject in the widget looks like that:

So It comes from the OnDrop’s Operation’s payload.
Which is created in the ItemWidget and thats where I add the ItemObject to the Operation.

“GetDefaultItemObject”

TryAddItem

ItemObject

TryAddItemObject

Those are all functions/objects that only exist in your project and will do what you implemented them to do. If you call a function (e. g. “TryAddItem”) then it will execute locally. If the client wants to tell the server something, you can only do this via a RunOnServer event (which means the client asks the server to execute that event on the server).

I don’t know how you implemented those functions do, so I can’t tell you what they will do.


Generally speaking if you want to build an inventory then two ways you could do it (there are ofc more)

(-) only save an item key and the amount. So your inventory is an array of item key amount structures. If you want to spawn an item, you would get its data from the key and spawn it. If you want that spawned item to replicate, then the client would send a RunOnServer event to the server telling the server the item key and the amount to spawn and the server would spawn them. If you want to add an item to the inventory, then you add it locally on the server and locally on the client (you could also just add it on the server and replicate the inventory, so mark the array of structs to replicate but that would mean that every time it changes the server would send the whole inventory which is a bad idea). This approach would mean that the items can’t have persistant states or would result in a workaround to get persistant states. This is what I currently use and I have additional data for weapons to save a sort of persistant state for those.

(-) use an object per item. So your inventory is an array of objects where each object stands for one item. Since you have one object per item you can easily have persistant states in your items. All those objects would need to exist on the server. That means that if you want to add an item to your inventory it can only happen on the server and the spawning of the item object needs to happen on the server. Now the server would need the information that it should put into the item object from the client. So you would need to either send a bunch of variables to the server or make a struct containing those variables and send that struct to the server. The server then spawns the item object and sets its variables with what the client send to the server.

Now if you want to spawn an item, then the client would send a RunOnServer event to the server telling it which item object data to use for the spawning. For example you could make the item object replicate and then send an item object reference (a reference to an item object that exists on the server) from the client to the server.


Also if you use an already existing inventory system that was build for single player, then for multiplayer it would be easier to rewrite it from scratch than to try making an inventory system based on objects designed for single player working in multiplayer.

Wow! Thank you for this answer! Now I understand everything. :smiley: