Issues Surrounding GKPlayer's playerId Deprecation in iOS 13

I watched the video on Game Center Player Identifiers and saw that GKPlayer's playerId is deprecated in iOS 13, to be replaced with gamePlayerId and teamPlayerId. https://developer.apple.com/videos/play/wwdc2019/615/


Our games allow players to login with Game Center to join and play games hosted on our servers. We use playerId to identify players so that they can play and earn rating points under their own account. The video says to transition to using teamPlayerId to identify players, which by itself isn't too complicated, but I'm concerned that this hasn't been fully thought through and some players may lose access to their accounts in systems like ours.


1. As player's login during the transition period, we will need to read both playerId and teamPlayerId in order to change their account on our servers to the new id. After the transition, when playerId is removed from iOS, it seems that any player who hasn't logged in, perhaps returning to the app after a long break, will no longer be able to access their previous account. They will appear to us as a completely new player. It seems we need some proactive way, like a server API, to convert playerId values to the new teamPlayerId.


2. In the video, the presenter says that there is a "very rare case" when teamPlayerId and gamePlayerId will not be available to uniquely identify the player. In this case, we will have no method of identifying the player and allowing them to access an account on our servers. Nothing is explained about what this "very rare case" is or how to help users correct this. Slide 13 shows how to check for the error case, but does not provide any example error message or error handling.


3. We use GKLocalPlayer's generateIdentityVerificationSignatureWithCompletionHandler API to authenticate players on our servers. This API has not been updated, and it's documentation still says to use playerId. It seems a new API will be needed to deal with players having multiple, different ids.


I'm interested to hear from other developers who use Game Center as a login method for their own servers and are facing these kinds of issues. I'm hoping this post might get the attention of someone at Apple, but I'll also try to engage them in other ways and report anything I find out.

+1


We really need updated information about generateIdentityVerificationSignatureWithCompletionHandler

Is there still no way to authenticate a player using the gamePlayerId/teamPlayerId?


We're also using generateIdentityVerificationSignatureWithCompletionHandler and switching to gamePlayerId causes the verification to fail.

I don't know of any way to authenticate with gamePlayerId/teamPlayerId. We're still authenticating only the deprecated playerId, but are sending and storing the new ids, so we'll be prepared for the day when playerId goes away.

Has anyone successfully used GKPlayer.loadPlayers(forIdentifiers: , withCompletionHandler:) using either gamePlayerIDs or teamPlayerIDs for as "forIdentifiers"?


My game happily used loadPlayer() for playerIDs (since deprecated), but I always get an empty GKPlayer array (no error code) from using the function now with gamePlayerIDs or teamPlayerIDs. Build 12.4.

FYI, .playerID is still working in iOS 13, though it likely will stop working in a future version. Perhaps this info is useful to someone.

Here are my findings regarding gamePlayerIDs and teamPlayerIDs:


1. I can get the localPlayer's gamePlayerID and teamPlayerID with no problem. I have never had scopedIDsArePersistent be false. However, for my app the two IDs are the same, for some reason. The teamPlayerID is of the form "T:_<32 hex digits>", whereas the old playerID used to be "G:<10 decimal digits>".


2. I can NOT get the teamPlayerID for an opponent. In a real-time match, [myGKMatch.players objectAtIndex:0].scopedIDsArePersistent is always false. If I attempt to read the teamPlayerID field anyway, I get a 16 digit hex string (with no "T:_" prefix), and this string doesn't ever appear to be the same string twice, even for the same opponent. I also tried this with a turn-based match, where I found the opponent's GKPlayer through a GKTurnBasedParticipant array, with the same results.


I don't know if we are supposed to be able to get the teamPlayerID of an opponent, but this always used to work for playerIDs.

We put some analytics in our apps that track the return values of scopedIDsArePersistent for the local player, and we are seeing a small percentage of players on iOS 13 where the value is false, as Apple said to expect. Once playerId is gone, I'm still not sure how we're supposed to identify these users on our servers. On iOS 12.4, scopedIDsArePersistent was not available, but we have still seen users where the game/team player ids have changed. As a result, we have users accounts in our system that have a single "G:" or "U:" playerId value, but multiple "A:" and "T:" values. I went ahead and filed a bug report for this (FB7137603). We're also seeing another bug where occassionally we receive the values "UnknownID" and "Unavailable Player Identification" for the game/team player ids (FB7137454), so we're ignoring those values now. Coinciding with the public release of iOS 13.0, we also started receiving some empty string values for game/team player ids.

Thanks, this is good info. I'm testing in a non-production environment, so I don't have many data points.

Just another +1, particularly with regards to an updated generateIdentityVerificationSignature method.


In addition, I'd add that watchOS does not support gamePlayerID or teamPlayerID, making the only option on that platform deprecated.

Hello everyone. I am new here. Thanks for the useful information 😉

Obviously relevant at the moment.


I'm attempting to finalize my first Game Center game after years of watching the APIs, and I'm not succeeding in finding out how to use the new scoped IDs while avoiding playerID entirely. For example, I can't see there's even one available pattern for obtaining scoped identifiers for the local player's Game Center friends in order to invite them to a match. Meanwhile, the existing methods for this pattern – obtaining and using a playerID to form a match request – appear to have been deprecated as well.


I get the feeling WWDC 2020 is going to bring a wave of clarity along with some of this seemingly unreplaced functionality, and that the video presentation about the scoped identifiers are more of a sneak peek than a true call for conversion to what will replace it. But that's entirely inference, and that clarity seems merited at the mention of these new APIs and deprecations.

I decided to keep using playerID for now, and to stash away a mapping between that and gamePlayerID/teamPlayerID when scopedIDsArePersistent indicates that those are not transient. I'll figure out how to transition data associated with playerID when/if clarity is provided.

Agreed – I think for now I just have to proceed as though the scoped IDs weren't announced yet.

Okay, I'm working things out. As seems to be the case with much of Game Center, there seem to be design intentions belied, rather than explained, by the documentation.


To set up a match with the Local Player's friends, there's no need to use identifiers at all – I'd just missed the one method that still returns GKPlayers for friends: `loadRecentPlayers`. Its name doesn't mention friends, but there's an afterthought in the documentation which mentions it also returns players from the "legacy friends list." (I wonder how it's "legacy" – you can add people to it in iOS 13.)


gamePlayerID and teamPlayerID appear to work: you can access them and store them. But for players other than the Local Player, they seem, intentionally, not to persist between app launches or connections to Game Center. They change every time. Apparently they just can't be used for data persistence in the way playerIDs could be.

I started to play around with teamPlayerID value since Apple indicated in most cases we would be using the teamPlayerID value.


A) Once a match has been created, the teamPlayerID can be obtained for each player by looping through each player in the match (myMatch) data provided


for player in myMatch.players 
{ 
   print("teamPlayerID = \(player.teamPlayerID)") 
}


B) The teamPlayerID can also be obtained by calling the GKPlayer.loadPlayers(forIdentifiers:) function to obtain all player information. You can then loop through the provided GKPlayer "players" array to obtain the teamPlayerID for each player.


let playerIDs = myMatch!.players.map { $0.playerID } as [String] 
GKPlayer.loadPlayers(forIdentifiers: playerIDs) { (players, error) in ... 
for myGKPlayer in players 
{ 
   print("teamPlayerID = \(myGKPlayer.teamPlayerID)") 
}

(Note: Creating the player map array using $0.teamPlayerID does not result in any data being returned)



Issues Found:


1) If Player1 performs (A) and (B) then they will notice the teamPlayerID values for each player in the match from (A) are not the same values as the ones from (B)


2) If Player1 performs (A) and Player2 performs (A), then both players will have different teamPlayerID associated with them both? Meaning ...

  • Player1 sees a different teamPlayerID value for Player2 than Player2 sees for themselves
  • Player2 sees a different teamPlayerID value for Player1 than Player1 sees for themselves


3) Calling myGKPlayer.scopedIDsArePersistent( ) for each GKPlayer in the provided players array, in (B) above, always returns FALSE.


As a result of these issues, it does not seem the teamPlayerID value can be used to uniquely specify a particular "player" like everyone has mentioned.


I also confirmed one player cannot send data to another player (via GameKitHelper) since both players do not have the same teamPlayerID values that represent each player in the match.


The WWDC2019 video indicates the teamPlayerID values would remain consistent between all applications produced by my team, however, I clearly see the teamPlayerID value does not remain consistent within one single application only.


I will have to keep using playerID value until proper usage can be explained/fixed.

I'm in exactly the same situation as you. I've been using playerID for authentication for years.


By deprecating playerID, Apple is basically deleting all my users' accounts and data. Because what's the difference between losing your account and data, and not being able to log in to access it?


This will be a data loss "bug" on a spectacular scale.


I have started storing teamPlayerID/playerID pairs on my server but am already running into problems. At least one player on my server has a teamPlayerID of "Unavailable Player Identification" but a valid playerID. I have no idea what to do about this.


So you are not alone here. Any news from Apple?

Any update on this status? the team/game player ids not being consistent for a player will mean people losing their saved data.
We have the same problem and I am just here bumping this thread, hoping from a reply from Apple!
I wanted to provide an update on the issues we're continuing to see with teamPlayerID. We've continued to collect teamPlayerID values for our users, as an additional identifier for their accounts. However, we are still dependent on the deprecated playerID identifier for two reasons:
  1. On any given day, we are seeing that scopedIDsArePersistent is false for about 1% of our Game Center users. In this case, teamPlayerID is just a transient value and we don't collect it. Apple described that scopedIDsArePersistent could be false in a "very rare case", but in our opinion, this is happening much more often than we would consider "very rare". Obviously, when scopedIDsArePersistent is false, there is no alternative API to reliably identify users other than the deprecated playerID. We have reported this issue to Apple (FB8988340).

  2. Even when scopedIDsArePersistent is true, teamPlayerID can change for the same Game Center user. We've been collecting teamPlayerID as an additional identifier for user accounts only when scopedIDsArePersistent is true, but we still have accounts with multiple team-scoped identifiers associated with them. These accounts have one playerID identifier starting with "G:" or "U:", but can have two, three, or more associated identifiers starting with "T:". This bug seems to be very common. We have about 100 occurrences a day where we add a new team-scoped identifier to the account for a user that already had a different team-scoped identifier associated with it. This bug has been reported to Apple multiple times (FB8988326, FB7137603).

We believe that Apple deprecated playerID because it can be abused to track users across apps. Because of this, we are assuming the worst, which is that Apple will remove playerID before it has fixed the problems with teamPlayerID. While we would prefer to continue using Game Center if it is fixed, we have started making preparations to prompt our Game Center users to migrate to other login options, like Facebook, Google, and Sign In with Apple. I'd be interested to hear if other developers are encountering the same issues I mentioned above.

I'm experiencing similar issues, e.g. teamPlayerID and gamePlayerID are both "UnknownID". This just started happening between 2 devices and 2 GC accounts that used to work (my own devices and accounts). Not sure how to fix this so I'm wondering if there's any response from Apple on the bug reports reported by @RajDoshi.

I noticed that when switching Game Center accounts the GKLocalPlayer authenticateHandler is called 3 times in quick succession (which in itself is not ideal). The first 2 times teamPlayerID and gamePlayerID return "UnknownID" but on the 3rd call it displays the correct IDs. However, the legacy playerID displays correctly all 3 times.

The GKPlayerAuthenticationDidChangeNotificationName which I have used in the past to reliably track users changing accounts is only called once on switch which is correct, however, it returns "UnknownID" for teamPlayerID and gamePlayerID, rendering it unusable unless I stick with the legacy playerID which still works as expected.

Since the authenticateHandler returns the correct IDs eventually, I could work around it by ignoring invalid IDs and waiting until they become valid. But this would be hacky, and leave me having to check against a particular ID format which is usually not recommended as the formats could change.

It's 2024 and I'm also heavily considering sticking with the legacy playerID as it works perfectly.

Issues Surrounding GKPlayer's playerId Deprecation in iOS 13
 
 
Q