Make sure all players are ready

Hello,

I have a listen server game where the players are loading videos. Because I want the videos to be played simultaneously it is important to make sure all players finished loading the video. This can happen milliseconds or minutes apart from each other. My approach is the following: Once a client (or server) has finished loading, call an event on the server (Replicates on server) which will then increase an integer variable. If the variable then matches the amount of players, all players are ready. Sadly, this does not seem to work since the variable will only be increased by 1 even if the method gets called 3 times. One reason could be that the method may be called at the same moment, however, it also happens if I call it with a random delay.

Does someone have a smart solution on how to make sure all players are ready, before multicasting an event?

Why don’t you do it like this. In your game mode override methods on OnPostLogin, and OnPostLogout.

You will get PlayerController from those methods. You can get PlayerState from it. Store player states in some array in GameState when player joins, and remove it when player LogsOut.

In PlayerState create replicated boolean variable that will track when player is ready.

In PlayerState create Event that is Replicated → RunOnServer. Whenever any of the players is ready, call the method from the clients side.

Now last step, whenever that event is called, make sure to call some method in GameState. That method in game state should iterate through the whole list of player states, and check if all of them are ready. If they are, do your magic. Please don’t do it on GameState::Tick method :slight_smile:

Please note the difference between the PlayerState and PlayerController. Same as with GameMode, and GameState.

3 Likes

Thank you so much Bojann for your help. Your approach works great and helped me understand ue4 way more. However, I have a follow up question:

This is my blueprint for MyPlayerState:

This is the log that get’s produced for three players:

LogBlueprintUserMessages: [MyCharacterPawn_C_0] Server: Stream URL Set: …
LogBlueprintUserMessages: [MyPlayerState_C_0] Server: Media Opened: …
LogBlueprintUserMessages: [MyPlayerState_C_0] Server: Player 272 is ready
LogBlueprintUserMessages: [MyGameStateBase_C_0] Server: VideoReady: 1/3
LogBlueprintUserMessages: [MyPlayerState_C_1] Server: Media Opened: …
LogBlueprintUserMessages: [MyPlayerState_C_1] Server: Player 273 is ready
LogBlueprintUserMessages: [MyGameStateBase_C_0] Server: VideoReady: 2/3
LogBlueprintUserMessages: [MyPlayerState_C_2] Server: Media Opened: …
LogBlueprintUserMessages: [MyPlayerState_C_2] Server: Player 274 is ready
LogBlueprintUserMessages: [MyGameStateBase_C_0] Server: VideoReady: 3/3
LogBlueprintUserMessages: [MyGameStateBase_C_0] Server: Video ready for everyone
LogBlueprintUserMessages: [MyPlayerState_C_2] Server: Player 274 is ready
LogBlueprintUserMessages: [MyGameStateBase_C_0] Server: VideoReady: 3/3
LogBlueprintUserMessages: [MyGameStateBase_C_0] Server: Video ready for everyone
LogBlueprintUserMessages: [MyPlayerState_C_1] Server: Player 273 is ready
LogBlueprintUserMessages: [MyGameStateBase_C_0] Server: VideoReady: 3/3
LogBlueprintUserMessages: [MyGameStateBase_C_0] Server: Video ready for everyone

The log shows that everything works correctly but the method is called twice for the clients (Last 6 lines).
Note that “OnMediaOpened” is only called 3 times and “PlayerIsReady” is called 5 times.
I am sure I can figure out a workaround here, but I was wondering if I don’t understand the RunOnServer replication correctly. Is it meant to be executed twice for clients? And if so, how can I stop it from doing that?

You are welcome, I’m happy that you made it work.

Whenever you create replicated actor in online game, you will have two of the same actors. One for the Client, and one for the Server. What you did in Event Begin Play get executed on both, and therefore you have two calls. Register event only on clients side. You can create new event for that, and make it Replicated -> Client.

To summerise, Bind Event to On Media Opened is not needed on Server side. Only on Client side.

1 Like

But why is the “Media Opened: …” log not written 5 times? It seems that only the event “PlayerIsReady” get’s called an additional time for the clients (but not the “OnMediaOpened” event).

Even though you have set binding on the class itselt, and it is binded on server and the client, it does not get executed on server and client. It is only executed on the client because client is setting it to ready. You have 3 clients, and therefore it get executed only 3 times.

If playerReady event is on the server, it should only get executed 3 times also. But you can put some debug points and investigate source of the calls. I don’t have your project, and therefore can’t tell what’s going on.