Client RPC gets called sometimes on the Client

Greetings, Hope everyone is doing good today.

I’m having a small issue perhaps someone can point me in the right direction. Its relevant to network replication. I have a RunOnClient that gets called sometimes, and sometimes doesn’t. What I mean is that there is a function marked as (Client, Reliable) on the PlayerController that is always called on the server side, but on the Client side, it gets called when it feels like it lol.

The framework is the following.

Server receives input from the client, verifies values.

Once the information has been Confirmed,

  1. Call GameMode function that calls a GameState function

  2. Runs logic, then it calls a Client function inside the PlayerController.

Breakpoints indicate, both the reference to the PlayerController is correct and the Function is in fact getting called… it’s just that sometimes the Client never calls it on his end.

Any tip is more than welcome!

As always Happy Dev’n!

UPDATE ----------------------------------------------

So I toggled between Reliable and Unreliable and had some interesting results.

  • Reliable : Whenever the function is not called on the Client side, I have to close down the Dedicated server and re-open it to try again, otherwise if I keep trying the input without closing the Dedicated server, it’ll keep calling the “Client” function but it’ll never be received on the Clients end.
  • Unreliable : When the function is not called on the Client side, I can just enter the input again and it does called not always on the second try, but surely in the next couple of tries without the need to close and re-open the Client or the Dedicated Server.

That is very weird indeed, The only time I’ve seen behavior like this is when something is not marked to be replicated (usually in the case of a component or subobject) or you are calling the “wrong” function, such as the case of an interface function with the same name as a function on your object.

In such cases I run the debugger in “GameDebug Editor” (so that operations do not get optimized away or occur in a funky order) and use the following:

ENetMode netMode = GetWorld()->GetNetMode();
ENetRole netRole = Role;

This code will only exist when your game is built with the editor and while debugging you can verify you are in the right world (Client, Server, etc) and what role the current actor has. Just throw a break point right there and when the code get’s executed it will halt execution and you can see the values by hovering over them in VS. Of course this is assuming your code is done in C++ haha.

Yes it is done through C++. I don’t really understand very well why it keeps calling the function on the server side with all of the correct values, but the breakpoints inside the Client function in the Playercontroller gets called sometimes…

Maybe I should explain a bit better how its manages.

I have a UDPComponent, that is created in the constructor of a UDPActor, which is Spawned through the Begin Play of the Level Actor with a (HasAuthority) to confirm we spawn as a Server.

So , Client inputs name → Tells UDP to send data to Other Dedicated server, → Once received, it verifies some logic and returns the answer, indicating if he in fact can choose that name → Calls UDP to send the info back to requesting Dedicated Server → Dedicated server calls GameMode Func → Calls GameState Func to confirm the requesting Client → Tells Client to call Run on Client function located in the player controller…

I don’t see what I’m missing… and what is annoying is that it works sometimes… Should I have bReplicates on both the UDP Actor and UDP Component?.. or where should I be looking for the error… again, the UDP communication is working fine since I am receiving the information and the values are all correct.

First of all, what you are doing sounds fascinating! Would love to see that code haha. So what it sounds like you are doing is communication between two dedicated servers and a client on one of them. Could it be possible that some times the function call is happening on the wrong dedicated server? Generally a component only needs to replicate if it needs to have values on the client (and I assume another server) and also to fire RPC calls. If your Actor is doing all the replicating and RPCs than the Component does not need to replicate.

Nah, it is being called on the correct Server. I have a on going server that manages the Matchmaking process, and is in charge of creating other dedicated servers to gather small groups in. Both of those server have different maps and different GameModes. I debug with breakpoints and the correct GameMode is being called once the small dedicated server is receiving the info back from the Matchmaking Server.

The only reason why I would see a Run On Client not being called is if the actor who is calling it is :

  • Not an Actor Class
  • That Actor is not replicated
  • The client doesn’t own that actor

So it doesn’t make sense… the Client RPC is a function created inside the PlayerController and that checks all of the boxes… its an Actor Class, Replicated and Owned by the Client. I even made sure that the value of the playercontroller reference is correct, and it is.

UPDATE ----------------------------------------------

I just noticed that if I run the on going server and Attach its process to C++ debugger… the code ALWAYS works. But once I detach it from the debugger, it goes back to not working… I don’t think I have ever had such issue.

UPDATE --------------------

Took me a while but was able to find out the issue. I was working with UDP Sockets, following Ramas tutorial on this topic. I didn’t pay attention to one of his remarks when working on with his sockets. the UDP socket runs on a different thread, this was the cause of the issue. It’s ok to have the UDP receiver for example run on his own thread, but when the information was received on the UDP, I had to made sure the logic of the game was running on the GameThread (AsyncTask(ENamedThreads::GameThread, {});

Otherwise it results as “Undefined Behavior” which is what I was struggling with. Thanks everyone!