RunOnServer event not being hit on Server

Hello,

I’m having trouble getting a simple client/server RunOnServer call working my project. But what’s odd is, I’ve done this in tutorials from brand new projects and it works very easily with little effort. I think there’s something wrong with the way my project is set up. Possibly related to my Pawn, or Level, actor ownership, or project settings. Can you please take a look and share some insight as to what I might be missing?

Background

  • I made a working proof of concept for a game and now I’m adding multiplayer functionality.
  • I can easily get client/server calls working in tutorial projects but for some reason not this project.
  • Unreal version 5.4
  • I don’t see any networking errors or warnings in the logs.
  • I’m using Switch Has Authority where needed (I think)
  • I have replication enabled on the Blueprint in which I’m working (BP_Board). For some reason it’s owner was none so I tried setting it manually but that didn’t fix the issue. But this may be related?
  • I’ve set RunOnServer exactly as seen in the tutorial
  • I’ve tried Multicast (instead of RunOnServer) and it seems that the other clients are receiving the event! But the Server is still not receiving the event. No idea how that’s possible because isn’t the server relaying the message to the other clients???
  • I’ve tried NetMode Play as Client with dedicated server, and Listen Server. I get the same problem on both
  • I’ve tried with only 1 client, 2 clients, etc. Same result.

One big difference I noticed from my project vs the tutorial that might be the problem: In my project, I’m setting my DefaultPawn in Project settings Maps & Modes to None. And then I’m creating my Pawn for Player0 and Pawn for Player1 inside my level. Each Pawn contains a camera. And I’m using Auto Possess Player to assign them to Player 0 and Player 1 respectively. Is that a good way to do it? Is my Player Pawn setup possibly to blame for why this isn’t working? See screenshots below.

Another difference between my project and tutorial: Owner of BP_Board was set to None/Null. So for some reason I had to Set the owner manually. But that still didn’t fix the issue. I wonder if somehow the server doesn’t see that the player owns BP_Board so it’s not replicating it. But I’m not sure how to fix that. Note: I Created BP_Board in the level, I did not spawn it dynamically. Idk if that matters. See screenshots below.

Another difference, in my project I’m making RunOnServer call within BP_Board, which is an actor I added to my level. Where as in the tutorial they are making RunOnServer calls in their Pawn (BP_ThirdPersonCharacter). Does that matter? I would assume I should be able to make client/server calls on any BP as long as ownership is set up correctly. That’s why I’m wondering if this is an ownership problem. But I’m not sure how to investigate this further…


My client event where the client presses F on keyboard


My server event, Run on Server Replication enabled. ROS_Test


My BP_Board blueprint class where these events exist, Replication is turned on in class defaults


Project Settings, Maps & Modes


Where I initialized BP_PlayerPawn0 in level


Where I initialized BP_PlayerPawn1 in level


I noticed BP_Board owner was null, so I set it manually here


BP_Board client & server running. Note I only had 1 client running in this test.


GM running on server


PlayerPawns running on client & server.

Logs from this test. You can clearly see things are getting initialized in OnBeginPlay. The client presses F, I can see the player controller is the owner of BP_Board, I’m calling the function on the server, but the server never receives the event!

LogBlueprintUserMessages: [None] Client initializing BP_PlayerPawn
LogBlueprintUserMessages: [None] Client initializing BP_PlayerPawn
LogBlueprintUserMessages: [None] Client initializing BP_Board
LogBlueprintUserMessages: [None] Client Pressed F
LogBlueprintUserMessages: [None] Owner = BP_PlayerController_C_0
LogBlueprintUserMessages: [None] Client: Before calling ROS_Test
LogBlueprintUserMessages: [None] I am client calling ROS_Test

If this was working I would see Server: ROS_Test. I should see this!. But I do not…

And finally, just a quick screenshot from the tutorial I was following, I was able to get this working without any issues. And aside from the differences mentioned above, doing this same thing doesn’t seem to work for me in my project

only had a quick look but my guess is this, you can only call RPC with ownership, if BP_Board is added to the level its owned by the server so clients cant call RPCs.

this fix is to call the RPC from the pawn and/or controller which you do own

So trying to understand proper multiplayer gaming architecture. Should I always be making requests from my Pawn or from my Controller? So let’s say some event happens within my BP_Board or BP_Card or BP_Weapon or whatever, BP_Board needs to call Pawn (for example), and then Pawn calls the RunOnServer? So all various actors will be making calls to Pawn and that’s normal? So then Pawn basically has ALL of my server calls in it?

Example: I have BP_Card on my BP_Board. Someone touches it, a touch event fires. Board needs to call Pawn which calls to the server.

Weird. Get this. I did what you suggested. But I found this


Screenshot 2025-03-10 at 12.03.59 PM
Inside BP_Board, GetPlayerPawn returns null. I’m assuming that’s not normal right? So maybe my Pawn is set up incorrectly in the game and that’s why the server cannot communicate with the BP_Board or the Pawn?



If I get my Player Pawn from the level, where I created it, using a tag this is what I see. It gets the BP_PlayerPawn0 which is correct, but it does not have an owner either! So maybe I’m not associating my player pawn with my player controller?

not exactly, to understand multiplayer, understand that everything happens on the server.
the server can tell anyone what to do but the player has to request (RPC Server) can i do this?

so anything that happens on the board happens on server. the players are only really RPC input, (i want to do this)

what is your pawn? usually its the pawn possessed by a controller, if its possessed by the controller, the controller should be the owner

Okay so here’s what I found now.

1.) I deleted my BP_PlayerPawns I created in the level.
2.) I changed my project settings to have BP_PlayerPawn be the Default Pawn Class. And ensured that my GM class is also pointing to BP_PlayerPawn as my default pawn class.
3.) Now the following is working! In my BP_PlayerPawn class, I can make calls to a RunOnServer event and it works correctly as expected!
4.) But my BP_Board still does NOT have an owner for some reason. And if I make a RunOnServer event in my BP_Board class, it still doesn’t work (Likely becuase it doesn’t have a proper owner set up…?)

So the above tell some that Creating Actors in the level is NOT correct because it doesn’t set up ownership properly. Where as if you spawn actors, it does set up ownership properly. But that begs the question, if I WANT to put an actor in my level and still have its ownership set up properly, how do I do that? I can’t seem to get that to work. If I just call SetOwner it doesn’t seem to work!

you’d think this would just work, setting the owner of BP_Board to the owner of GetPlayerPawn (which is now correct). But the RunOnServer call still fails even after I set this owner.

this is correct, consider multiplayer, there can only be one owner so not all players could own the board and call RPCs, so its considered to be owned by the server.

what you do is call the RPC from your pawn/controller with a reference to the board.

also obvious point but make sure the board is spawned by server and replicated

This was one of my big problems that wasn’t obvious to me at the time. I was spawning the board in the level and that was leading to this problem!

Thanks you rock!

1 Like