Multiplayer Client Variable Access... I just can't figure it out

Hello Unreal-ites,

Multiplayer: I have a (base) class that inherits from pawn. I have a player controller class that inherits from PlayerController. In the player controller class I have a reference to an instance of the pawn base class so I don’t have to cast to the base class each time I do something in the controller using this variable

This variable IS replicated. Why? The setup I have does NOT use a movement component on the pawn. Instead, input is captured in the controller and calls events on the pawn for manipulation. I use a SwitchHasAuthority macro at the end of each function in the pawn to run on server / multicast. This seems to work as I can test and see movement on clients and server.

Specifically, In GameMode, I drag off the controller from OnPostLogin and call Possess. Back in the Player Controller, in OnPossessed, I use the passed in Pawn, cast it to the appropriate type, and set the replicated variable. I then call a FUNCTION (not an event) to create a couple of Widgets. It is here I have problems. The problem comes when I want to access this variable from Client PlayerControllers.

I have a Main widget, and inside that there lives another Widget. The Main and Sub Widget have variables to refrence the pawn and are exposed on Create Widget. So, after setting the replicated variable in OnPossess on player controller, I use this variable as an argument to the Widget variable. It works perfectly fine on the server, but on the client the variable is null. I can’t quite understand why and i’ve been reading documentation, trying to find posts, anything that could help me. I have exhausted myself.

I am reaching out to you for help.

Sone things I have tried:

  1. Instead of calling the function from Controller.OnPossess, In the GameMode after I call Possess on Controller target, I call an event on PlayerController set to RunOnOwningClient. This calls the function, but has the exact same outcome: client shows variable is null while server’s variable (and setup) are good.

  2. In the Widget, I can use GetOwningPlayerPawn, but cannot use that on Initialize or Construct as it does not return anything. In Tick, I can test to see if the Widget pawn base VARIABLE is valid, and if not, then call GetOwningPlayerPawn, cast it, and set the Widget variable. Obviously this is a hack with tick checking this every frame. I did it as a test…

  3. On the controller side, I call GetControlledPawn but on the client, that’s null (on server that function works fine).

I’m not smart with a big blocks of text and don’t actually understand what you’re trying to do. Are you trying to make a widget in the client? Or access the widget in the client?
I might be able to help if you can provide screenshots.

Hello @SkeetonYu , I can provide screenshots when I get home. In short, PlayerController has a reference to the pawn which is a replicated variable. I have two widgets, both of which have a variable (same type as the one on playercontroller). It is exposed as an argument when using CreateWidget. However, client playercontroller variable is always null and can demonstrate with print statements. I don’t understand why the client playercontroller can’t read the pawn it owns.

The only thing I can think of top of my head is that the widget was created on the server side and so only the server has the variable. When you use the print statement, does it say client or server? That’ll usually tell you on which side the variable is on, server or client. So if it on server then it can only be called on server. If it on client then only the client can have access with it. Even if it was replicated.

Just find out what side the variable was set and then call it from that side.

Hey @SkeetonYu , The logs do show Client side, and Client side shows the replicated variable as being null. I apologize, I did not get a chance to post some images, but hopefully today I can gather some images to show you the setup across the various objects, the flow, and the logs.

I have uploaded screenshots as requested.

The names of the images are appropriate for what they are. In short: In the GameMode, upon OnPostLogin event, I call event SetupPlayerController shown in GameMode.jpg image. I wrap the code because it can’t fit on one screen, and zooming on the image is too fuzzy for you to see.

As you can see in that call, I set a player controller variable with the spawned actor. Near the end of that event, I call an event RunOnOwningClient called Event InitializeMainHUD. This image is named appropriately. All this event does is call a function. The function takes care of the work and the image is named appropriately.

I also have two output files… one shows the log itself, the other shows a side by side image of the printstring data in the function so you can see easily.

As you can see, client 1 shows nothing for the controlled pawn (despite calling Possess from Server event on that playercontroller) and the variable APlaneBase set just after the Possess node on the server, using the logged in playercontroller.

GameMode:

PlayerController Event InitializeMainHUD

PlayerController CreateAndDisplayMainHUD Function (not an event):

Log SideBySide:

image of the log:

APlaneBase looks like it’s being made in GameMode which is always server side. The actor will spawn but all the variables being set is only in server side. Now the hard part is trying to figure how to get to the gamemode on client and then return the APlaneBase value back to client. I know GameState has access to both GameMode and Player Controllers but I think you can also access GameMode with Player Controller.

But that’s what I’m seeing though. APlaneBase is being spawn and replicated to all but not the variables that are being set. That is only done in server side.