When is a Client PlayerState first guaranteed to be valid and ready for use?

I have a Widget that sets up a callback from an event in the PlayerState. This works fine on the Server, but I found that sometimes (~25% on a local test using play-in-editor) the PlayerState is still null in Client’s Widget’s OnInitialized Event. With a 0.2s delay added, everything works 100%, emphasizing that it’s just a synchronization issue.

The first link below offers a solution of just polling (for instance when a HUD element is drawn) to see if the PlayerState is valid, and then doing your initialization there when it becomes valid. Is there a cleaner way?


Probably the same issue described (in detail): Client Playerstate in HUD sometimes invalid

Probably the same issue (without detail): How can I guarantee that the playerstate is valid?

The simplest way to ensure the PlayerState is valid is to make the call from within the PlayerState BeginPlay to the Widget.
Getting the reference from a Character/Pawn can be guaranteed from OnRep_PlayerState granted the variable is in fact valid.

Getting the reference to the PlayerState doesn’t guarantee that the variables within the PlayerState are replicated yet so you furthermore have to use OnRep_MyVariable callbacks to ensure things gets updated as they arrive.

The way I ended up solving this was changing when the HUD is first hooked up. Before I was hooking things up in the BeginPlay method of PlayerController. Instead of that, now I’ve exposed the BeginPlayingState method inside of PlayerController and hook my HUD up once that is called. Now everything is working 100% and in a pretty elegant way.

I’m not sure why BeginPlayingState isn’t exposed to Blueprint by default.

Note that Pawns in Unreal Engine have an OnRep_PlayerState() function that’s called when the player state of a pawn is received on clients.
Additionally, there’s an OnPlayerStateChanged dispatcher that’s called on both the server and clients when the PlayerState is changed.

Conversely, the PlayerState class has an OnPawnSet dispatcher that’s called when the Pawn changes.