I have added an round variable to my GameState which gets replicated. After each kill it gets incremented and a multicast delegate event gets broadcasted.
Now in my HUD (UserWidget) I would like to show this round number. So within the NativeOnInitialized function I like to add AddDynamic on this dynamic multi-cast delegate. For some reason it works on the Client but not on the listen Server.
On the Server the GameState within the NativeOnInitialized is not valid or replicated yet. The Server goes into the else and logs “GameState not Ready”.
Any ideas on how to implement such a round timer in a userwidget?
AWGameState* GameState = GetWorld()->GetGameState<AWGameState>();
UE_LOG(LogW_UI, Warning, TEXT("Binding UpdateRound Event"));
UE_LOG(LogW_UI, Warning, TEXT("GameState not Ready"));
Widgets cannot see the server, so you cannot communicate between them. If you need to send a message from the widget to the server, then you will have to channel that message through a class such as the HUD or PlayerController.
The purpose of the GameState is to naturally replicate game data from the server to connected clients. Classes such as widgets that can obtain information from the server and other clients without needing to obtain this information manually.
However, it is not designed to the work the other way, i.e. widgets using the game state to dictate what the server should be doing.
Hope this helps
thanks for your reply.
I dont want the UserWidget to send data to the GameState. What I want to try is that the UserWidget listen to the OnNewRound multicast, which is broadcasted by the GameState. But for some reason the UserWidget is created before the GameState is ready or replicated on listen server.
I’m not sure, but is this even the correct way to display information from the GameState, or is there a better way to do this?
Apologies for the delay (Christmas period and all that).
One way to go would be to use an event dispatcher and have the widget listen for the OnNewRound event to be called.
Create an event dispatcher inside the Game State something like OnNewRoundReceived. Call the event from OnNewRound.
Inside the widget store a reference to the Game State on OnConstruct. With the Game State reference bind an event inside your widget to the OnNewRoundReceived dispatcher. Add any logic to the event inside the widget to update the UI.
Now once OnNewRound gets called, it will fire the event OnNewRoundReceived any objects listening to that event will receive a notification and then fire your custom logic.
Hope this helps
thanks, that does help me. I’ll try this out.
There is absolutely no reason to save a reference to the GameState when all you want is to bind to a delegate. It is a bad habit taught by many sketchy tutorials out there.
When are you creating the widget since it should not be created prior to the GameState reference being valid which happens PostInitializeComponents before BeginPlay.
so if I understand you correctly, you would prefer creating the widget on the PostInitializeComponents of the GameState? And in my Widgets OnConstruct I call GetGameState and bind to the delegate on it directly instead of setting a reference to it.