After a client joins when is it safe for a client to send an RPC to the server?

Using a listen server setup. Trying to send some data (player color) from the client to the server, so then the server can replicate it back out to all other players via replicated variable.

Currently, my customization system works great in game. Players can join and then chose their colour (and a ton of other customization things) and all other players can see these changes happening. Works great. I am saving these customizations via Save game, so after they quite the game, next time the player joins a game, their player will automatically set up to have the same customizations when they join.

So I have that save data, and I am trying to apply it on the client’s character when that character is automatically spawned on join. But in OnBeginPlay, when I try and send an RPC from that client → server saying “these are my customizations I want to have immediately!” that RPC just never makes it to the server. However, if I put a DELAY 1.0s node before calling the RPC everything works fine (or if I manually trigger the RPC some other way any time after the 1.0s)

It seems that I am just trying to send data to the server, before the connection/something is all setup? Is there a better entry point to do this? Or some other issue that is causing this that I am just not aware of? Looking at the logs from the OnBeginPlay on my Client’s player, it does log this warning:

ogNet: Warning: UNetDriver::ProcessRemoteFunction: No owning connection for actor BP_Character_C_1. Function S_RPCTest will not be processed.

But I’m not sure how I resolve that

Additionally, I have tried using the “Event Receive Controller Changed” event, to wait for the server to assign the controller to the client/player, to ensure that the “connection is ready to go”, but I get even weirder issues there. In the below test I am not calling my RPC until both OnBeginPlay AND OnControllerChanged is called on the locally controlled actor, to ensure the Actor is ready to have visual changes happen AND the controller signaling it’s net-ready. But the lines marked with * leave me very confused.

Server Starts
Server Char0 OnControllerChanged called
Server Char0 OnBeginPlay called
Server Char0 Set Initial Customization Data, since server is the owner of Char0 player (success visually we see this working)

Client Starts
Server Char1 OnBeginPlay called
Server Char1 OnControllerChanged called
Server Char1 Does NOT set data, because server is not the owner/controller of Character1, the client is
Visually, we see Char0 on client window with the correct data

Client Char0 OnControllerChanged called (irrelevant, since Character0 is the server's player, we don't care about that as the client?)
Client Char0 OnBeginPlay called
*Client Char0 IS locally controlled??? But thats the servers player? (IsLocallyControlled and IsLocalPlayerController = true)
Client Char0 Set Initial Customization Data (RPC never makes it to the server still, but it shouldn't have been sent anyways since this is not our player!)
Client Char1 OnBeginPlay called
**Client Char1 OnControllerChanged NEVER gets called, and so never sends data to the server.

No more logs
Visually, the client sees both players with the correct data
The server sees themselves with the correct data, but NOT the clients character (missing customization data)

So I’m just very confused. What is the proper way to send client data to the server, so the server can have that as soon as possible after the client has connected/joined? Anyone have any advice or things for me to try? Seems like just “leaving a delay before calling the rpc” is a nasty hack that I’m worried won’t actually work in all network conditions.

Edit: Regarding the IsLocallyControlled confusion above, in OnBegnPlay, I found this thread from 10 years ago that says IsLocallyControlled is not yet setup properly in OnBeginPlay yet… assuming that is still the case. Is Locally Controlled returns True for remote players? - #3 by Ryan_Gerleve


This is my super simple example, happening on the player pawn (which is basically the Third Person demo character). S_RPC that is sent from the client-> server never shows up in the log. If I add a delay in the EventBeginPlay of 1.0, S_RPC does get called. What is the proper way to do this, that doesn’t rely on a delay? How can I know the actor is net-ready and can send off RPCs properly (and nothing behind the scenes is still being resolved on the network/setup?)

try setting a bool IsInit by the server on repnotify and then in the repnotify event the client should be ready.

i havent had the problem you have though, what i always do is have my playercontroller spawn its own pawn (rather than gamemode defaults) so i can pass through any variables i need set, duing this should ensure the player is set and therefore IsLocallyControlled should work

Thank you for the reply. Yes, I considered using a variable on the server and wait for it to reach the client to know “things are good to go” when I receive it but seems like a messy workaround. Might be what I do for now though I guess!

Right now I am using the default “out of the box” setup for spawning players, but I do need to fix that up soon anyways to get a proper login/join game flow, and perhaps by doing that this whole issue will disappear anyways. Like you say controlling the spawn manually might be a solution

Begin play firing doesn’t mean that the controller has possessed the pawn or that possession has been replicated down to you.

For things like this I tend to lean on Timers when working with BP.
Also I use rep notify vars. The onrep function it creates is used to apply the changes.


1 Like