It seems like when you connect to the server, your client gets a call to remove the widget. When you close the server, the client is then kicked out and reloads thus creating the widget again just like if you started the game.
In regards to the other questions, as far as I know AHUD in the PlayerController is not replicated. (In PlayerController.h, AHUD only has a default UPROPERTY(), no sign of replication. Unless your AHUD belongs to something else, then I’m not sure, and will look into the source code for that. But the chances of AHUD being replicated is low, as it doesn’t make sense.
AddToViewport() seems to add the widget for everyone. If I’m not mistaken because I just had an issue with it. If the server tell its PlayerController that is for a client to AddToViewport, and then the client also does a AddToViewport, the result is two widgets for the client. Don’t quote me on this, but that’s what happened from what I remember, and I had to add a check on server side to check if the PlayerController was local before calling the bunch of code that setup the widgets for the PlayerController.
As to finding where everything can be replicated, seems like the best option as of now is to look to the source code and see if it has a replicated property to it.
All right so here is how I fixed it for people who are interested in.
The first thing to notice is that when you will run the client executable, it will first create bunch of temporary classes while waiting to be connected to the server. That means, for a moment, the client will behave like a “standalone” single player game.That means, it will have the ROLE_Authority and so on until it get connected to the server.
Correct me if I’m wrong about this.
So first, while being in this “temporary” state, my client creates some widgets. Then the connection with the server occurs and I think most of classes are reseted to their “network/connected” state. That involve destruction of objects instances and construction again.
That could explain why my widget disappear when I connect to the server, and reappears again when disconnecting.
SO, to solve this issue, I implemented the function MyGameMode::PostLogin() in which I call clients RPCs to tell them “You are connected, you can now safely create what you need”.
Here is the full function
void AMode_Base::PostLogin(APlayerController * NewPlayer)
UGameInstance_Base* GameInstance = Cast<UGameInstance_Base>(GetWorld()->GetGameInstance());
// This code is only executed on the server side
// Some peole would say "Wait, GameMode only exists on servers". Yes! But during the short time the client is still connecting to the server, the client behave like a standalone game so it will have a GameMode too !
if (GameInstance && GameInstance->ExecutableType == EPoliceExecutableType::POLICE_EXEC_SERVER)
AController_Base* Controller = Cast<AController_Base>(NewPlayer);
// Call client's RPC
I would love to hear some feedbacks about this post cause I think it’s an important concept to understand to get into Unreal Network stuff.
Creating widget stuff after PostLogin sounds right.
Not sure about the whole temporary thing. I know that when you launch the game, you have a GameMode, but once you connect to the server, specifically when the Server’s GameMode does PostLogin, the client will definitely not have a GameMode. I wouldn’t exactly call it temporary, just that is acts as a standalone. The game can not be considered a client until it is connecting or connected to the server in my opinion.
Thus your if statement for checking GameInstance doesn’t seem necessary for checking if it’s a server, since client will never have a GameMode in PostLogin, and even before that, since that ruins the whole point of GameMode being server-side only.
Unless the ClientTravel is SeamlessTravel I’m pretty sure everything gets trashed including the widgets. (Except for GameInstance stuff, which I would assume is used to handle things related to the Instance of the game, such as keybind settings.)
I hope your previous issue, wasn’t the fact that you never created the widget after connecting to the server. Since I already assumed you created the widget after you confirmed the client has connected, and then it was disappearing for you for some reason. Thus seeing your “solution” came as a surprise for me, as I assumed that was something you had already done.
Yeah, the documentation can be quite lacking at certain areas. As far as I’m aware, the documentation doesn’t talk about connecting to a server. Only thing I’ve found that is most related is traveling in multiplayer, but that’s for clientTravel that occurs when a client is already connected to a server.
I mostly read through the Engine’s source code to figure how it works. Thankfully the tricky areas in the Engine do have some good comments in them. So that helps in understanding how some specific niche part of the Engine works.
void AMyPlayerController::PlayerTick(float DeltaTime)
//** This will run for the first tick on the server/standalone
if (bIsPlayerFirstTick && Role == ROLE_Authority)
//** My function to show the UMG widget
bIsPlayerFirstTick = false;
//** This will run on the client and check whether the game state is ready
if (MyGameState == nullptr && Role < ROLE_Authority)
MyGameState = (GetWorld() != nullptr ? GetWorld()->GetGameState<AMyGameState>() : nullptr);
//** My function to show the UMG widget
Thank you so much for that solution. Based on that and my own investigations, I found that the AHUD is created after the PostLogin call. So I just create my HUD widget blueprints on BeginPlay of my HUD actor, which I find a lot more intuitive and does not require an additional replicated function call. Plus the HUD is always local to it’s PlayerController, so there is no need to check for remote roles or anything like that.
To make sure the Widget is destroyed, when the HUD is destroyed, simply call Destroy on the Widget, on Destroyed and on EndPlay of your HUD class.