Using UE5.3 BP, replicated custom event as RPC, unreliable (for now)…
I can pass an Actor via an RPC from a Client to the Server. But when I try to pass the same Actor back through an RPC from the Server to the Client, None is passed instead.
When I multicast the same Actor, only the Server logs it being the correct Actor, all Clients see None passed.
Does BP’s RPC via events not allow Actors to pass from the Server to the Client?
Please don’t pass whole actor as parameter in RPC event. Why would you do that? Just pass elements that need to affect it such as (Damage, HP, Inventory… etc).
It is perfectly fine to pass an Actor pointer with a RPC but it needs to be a a pointer to an already replicated Actor otherwise everyone else will just get an invalid pointer.
I found a video on the web where they passed the pointer of an Actor from Server to Client and it recognized the proper pointer on the Client side for that Actor. But that was in C++.
I am using replicating custom events in BP. One from Client to Server, the other from Server to (a) the owning Client or (b) all Clients. The Actor is always passed by reference, because… BP.
The problem is the Client always receives None, even when I pass back the value it just received.
EDIT: I didn’t want to use the word reference in the OP because there were threads referring to passing C++ references in RPC, and I figured everyone would know that BP only passes object references in replicated custom events.
Maybe you aren’t being specific enough when trying to pass the actor reference back to the client. I’m certain you can send references back and forth via blueprint RPCs, but sometimes you need to communicate through a specific player controller or player state in a particular manner to get it there.
The server might just be reading an arbitrary actor and isn’t specifically sending it to the player controller or its character in question.
You could try and get the player controller you are trying to communicate and pass that through also with and cast to it specifically and then execute it on whatever pawn. If its not a pawn then you would probably need to pass through a reference to whatever actor and cast to it from your server RPC and then set an actor object reference on that actor so the client knows what the actor reference is.
You might have it setup correctly, but like the other guy said if the variable isn’t marked as replicated the it might not be showing simply because of that.
Well, to be honest I don’t think it is. I’ve published game that has multiple online game modes, and I have never passed an actor trhough the RPC. That is absolutely not needed. If you need any, or multiple, information from the actor, you pass only that information as a structure, and not the whole actor. Actor is to heavy, and will be heavy for the RPC itself. And, also you are creating dependency on the actor itself, instead only for the structure. This is why, when you enable replication on the actor, not everything is replicated, only the attributes you selected to be replicated (and some default stuff). All my actors are identified by the unique ID’s and if I need reference to some actor on the client / server, I just pass unique ID through the RPC, and find the actor by the ID. This is the way I think it should be done.
I would also like to hear other opinion about this, but I still don’t see any logic to pass such a heavy object as a actor, throught the RPC. Even if it’s reference to the replicated one. For me it’s much better to pass the needed data.
I’d like to hear more too, i’d presume its not sending through a whole actor just a Ref to that actor, which considering Actors are technically different between client and server I think Unreal is smart enough to use some built in UniqueID.
If so you could argue that the structure is heavier and also more of a dependency since AActor is a base class
It is actually the opposite that happens. When you pass a reference to a Actor you only pass the identifier of the Actor, when you pass a Struct you copy all the date.
If you want to use structs you should replicate them as a variable instead of an RPC since variable structs if setup correctly will only sync the parts that have changed. Sending a struct as RPC is one of the most expensive RPC’s you can make.
My code is passing the Object Reference, because BP only has Class Reference and Object Reference. It should be clear this is only an identifier so that the other end of the connection knows which Actor is being referenced. The Object’s data is not being sent across, nor would I ever do that.
I am telling the Server which seat of a vehicle I want my Pawn to sit in. The Server knows which Pawn is asking, because the RPC code is running within the Pawn’s BP. I am sending the reference to the Seat Actor.
The Client is asking the Server to decide if the Pawn is allowed to sit in that seat.
If the Server decides the Pawn can sit in that seat, it passes back the Reference to the Seat Actor to the Owning Client (it is in the Pawn’s BP).
This is important because the Pawn must know which Seat it is allowed to sit in. I don’t want the scenario where it is asking for Seat A, then when it asks for Seat B instead, it gets back from the Server “OK you can sit in the seat.” The Client has to know WHICH Seat the Server authorized it to sit in. So the Server must send back the Reference to the Seat Actor that it is authorizing the Pawn to sit in.
Or is there a better approach than what I am setting up here?
I know, as I stated above, that in C++, the Actor pointer can be passed from Server to Client. I just don’t get why the BP equivalent doesn’t work the same?
This was the problem. The Seat Actor, a child of the Vehicle Pawn, was not set to Replicate.
This isn’t intuitive. The Replicate property would suggest that the Actor’s properties will be replicated, which isn’t what I want. But it really doesn’t have any to replicate, so no worries…
That’s all good, but yor character is just an actor that can be destroyed and recreated. At least that was the case with cars in my game (if flipped over, I can reset it to the track). So how I resolved it. My PlayerState (not controller) had object that held all the needed info (car health, driver name, unique ID, ammunition… etc), and when actor that it was controlling is destroyed, data would remain since PlayerState stays alive. So, I would do the same in your case (not saying it is the best solution).
So Client says Character with unique ID 001 wants seat number 4, and server would get only this two info - Unique Id of the character and number of the seat.
Then, my game state (not mode) would find PlayerState with same Unique ID, and instruct it to take the seat 04.
Again, this is the way I would do it, maybe there is a better way, maybe I’m wrong. Just giving opinion on how I did things in my game where online works quite fine, even though it’s P2P
I was thinking about what you said about the Seat not being spawned (instantiated).
The owning Client would not request sitting if the Seat wasn’t present.
If the Client asks the Server to authorize sitting, then what if the Seat is destroyed on the Server by the time the request is received? Wouldn’t the Server marshal the reference into a None and thus would deny the request?
Then the Server notifies all the Clients of the sitting of the Pawn on the Seat. If the Seat on any Client doesn’t exist, wouldn’t the Client marshal the reference into None, and therefore the BP could detect the failure and handle it gracefully?
I may be incorrect with the assumptions above. I am interested to know of any scenario in which the reference was not None while referring to a Seat that was not instantiated in the scene, leading to an invalid reference crashing the game.
My last set of questions are in the context of if there is a delay…
I couldn’t see how the Clients nor the Server would marshal anything other than None if they no longer had the Seat when they received a reference to it. I was asking if such a scenario can be described.