The client’s playercontroller has the wrong playerstate all the time. I bind a button to press “e” and print the controller’s playerstate in playercontroller event graph. in 80% of the cases it goes wrong and many times there are duplicates, which means that client 1 and 2 have the same playerstate, they also get playerstate 0 sometimes. I want it to be PC_0=PS_0,PC_1=PS1,PC_2=PS_2. If I try to run via server with button press E, I always get the correct playerstate for the controller.
Have been trying to understand the problem myself for 2 weeks. So I would be grateful if anyone has any advice. I’m about to give up.
Player controllers only exist on the server and the owning client, so clients don’t know of other client’s player controllers
Player states will never be shared between players, and if the “name” of the player state object is the same, that’s irrelevant, and up to replication order, which might not be the same
All replicated objects have unique identifiers which means that it’s guaranteed that they point to the “same” object, and you can rely on this fact, even if the name of the object is not the same between clients
If you are using an online system such as Steam or EOS, Player States will also have a Unique Player ID, that can help you differentiate between the players
In the engine code, when the unique ID is not available, such as in the case of LAN, the IP and Player name are checked to connect a player state to a player
I’m not 100% sure the player state indices are the same on all clients, but at least according to the code comments they should be
Sounds like I need to use unique id in the future then. But to explain a little better: I start the game with 3 players and run as a listen server, have tested all net modes with same results. I want to use playerstate in a widget to hit the right player to change a variable when a button is pressed so that the number of coins changes. But since the client owns the widget, it becomes difficult to change variables in the playerstate if the client does not have the correct playerstate from the start.
Since I have the HUD that shows the number of coins for an individual player, I know that the playstate that is printed is also registered as right playerstate, and coin changes. Coins: Player1=PS 1 coin, Player2: PS 2 coins… It worked very well with this until I started using the widget.
Should I start using unique ID instead, is that the most common way in a multiplayer game?
Do client knows its uniqe ID?
Do you never use playerstate index in online multiplayer games?
I will probably get some answers to this when I start testing myself with unique ID, will have to redo some. But if you have any answers before that, I’m happy. I’ll get back to you how it goes anyway.
Don’t use any Gets that require an index. e.g. Get Player Controller requires an index.
You should be using Get Controller, then cast to the Player controller class.
Get Controller → Cast → Get PlayerState → cast → store reference
Game State stores a copy of all player states in an array [PlayerArray]. All clients have access to GameState, thus the player array. Therefore any client can look at the replicated copy of any players state.
I tried using player id. I can print it and I get the correct player id if I assume the id is the latest number of the 3 players I have, other players have lower numbers and are in order as it is replicated. . Have the HUD display of players id and if you bind this to playerstate_2 (ie player 3) I seem to find the right player in the widget through the ID. But playercontroller and playestate are wrong when I try to print it. This is a success for me and the only thing that is right, however, I don’t understand how this is possible to be found when everything else varies for each round.
But don’t get much out of it as I can’t extract playerstate from it.
What blueprint code is needed for this?
I have no problems store data linked to playerstate, but big problems getting the right playerstate linked to playercontroller in the client’s widget.
I tried in the widget to do as you say but still get the wrong playerstate. When I open the widget on player e.g. 3 (client 2), playerstate 0-2 can be printed completely randomly after every round I test. It means that my HUD is not updated in the correct place as my HUD has fixed positions. The only thing that currently works and is stable is player ID which seems to work in playerstate. But don’t know yet how to fish playerstate out of it.
What do you mean they’re wrong? On a client’s widget, GetOwningPlayer will return that player’s player controller, and the player state of that controller will always be that client’s player state, and this can never be wrong
Depending on when you initialize your UI, it might be possible that the player’s player state has not replicated yet, so you might have to wait, or keep retrying to get the player state from the controller with a delay (Controller → Get Player State → If not valid delay and Get Player State again, until Player State is valid). Under normal circumstances this should be nearly instant. There are ways to streamline this initialization so you ensure that everything you need is available before you show any UI, but that’s another topic
When a player joins the game mode creates a player controller and a player state. A player state reference is added to the game states player array. These typically should be indexed in the array according to join sort order.
In the controller class you should easily be able to get a specific player state via index with the following code.
Some examples. Sometimes multiple are playerstate0, and sometimes playerstate1. And sometimes in the correct order and sometimes in reverse. But of course server always keeps 0.
If a playerstate is invalid, you only get a zero, right?
Thanks! You gave me some new ideas how to do it too. Have used a similar method to. A little more complicated than necessary. A small snapshot of how I did many things for display in the HUD.
But as I’m losing more and more self-conceit, I tried to do like you and added my previous one to spawn players. Have used this tutorial: https://www.youtube.com/watch?v=H0JZnWdY0k8
But didn’t get any better results from them. You are welcome to look at my other answer if I am unclear.
If the player state is invalid the print will not get called
Like I said, the name of the object which is what you’re seeing with the print is not consistent for player states across clients
it doesn’t matter what that name is, and is completely up to replication order, which can be arbitrary
If you want to test, you can call GetPlayerName on the player state, and it should show you the name of the user connected, which should be, in your case, unique and consistent
Name gets assigned by the online subsystem, so for example it would be your steam or epic username, or your PC’s name plus some other identifier in LAN
Don’t complicate things too much, and in the vast majority of the times you can trust the engine is correct.
Player states also have something called PlayerID (which you can get in BP using GetPlayerId), which is a unique number assigned to each player
I’m sure if you print that it will be consistent every time
Also, something that I’ve noticed and is really important, there was a bug with 5.4 that caused the print string function to not return the correct client string, so all of them printed Client 0 (so much for “trust the engine” huh ). I think this was fixed in one of the hotfixes, so if you haven’t updated your engine, do that if you can. Otherwise, unfortunately you’ll have to find different ways to differentiate between different client debug prints
It’s starting to get into my head what you’re saying. Was a little too late to understand. I think I’m starting to understand. Was able to get the playerstate out correctly now. Just need to rework some code so it will be correct in my HUD.
But when you get off track, you start to lose understanding and you start doing things differently. Have read about bugs earlier so you become a bit thoughtful. Luckily I’m running 5.3.2
Everything flowed so well and crashes for a small thing.
I’m thinking I should move on after your and Rev’s response.
Many thanks Zeaf, I will close the thread when I really also see that my HUD is working as intended.