Create apps that allow players to interact with each other using GameKit.

Posts under GameKit tag

72 Posts

Post

Replies

Boosts

Views

Activity

Matchmaking issue on tvOS with GKMatchmakerViewController.Request
Hello ! We are working on a real-time 2-player online game targeting multiple Apple devices. The following issue only occurs on tvOS: When selecting matchmaking to connect with another random player, the native Game Center interface opens and begins the matchmaking process. Almost immediately after clicking "start", the following log appears in the console, and the matchmaking screen remains indefinitely without completing: Timeout while starting matching with request: <GKMatchRequestInternal 0x30d62f690> { defaultNumberOfPlayers : 0 isLateJoin : 0 localPlayerID : U:bea182d69b85f0839e3958742fbc4609 matchType : 0 maxPlayers : 2 minPlayers : 2 playerAttributes : 4294967295 playerGroup : 1 preloadedMatch : 0 recipientPlayerIDs : <__NSArrayM 0x3034ed5c0> {} recipients : <__NSArrayM 0x3034ee280> {} restrictToAutomatch : 0 version : 1 archivedSharePlayInviteeTokensFromProgrammaticInvite, inviteMessage, localizableInviteMessage, messagesBasedRecipients, properties, queueName, recipientProperties, rid, sessionToken : (null) } . Error: (null) However, as shown in the code snippet below, the task does not complete when the log appears. But when we manually cancel the matchmaking process, the "User cancel" log is correctly triggered. var gkMatchRequest = GKMatchRequest.Init(); gkMatchRequest.MinPlayers = 2; gkMatchRequest.MaxPlayers = 2; var matchRequestTask = GKMatchmakerViewController.Request(gkMatchRequest); matchRequestTask.ContinueWith(t => { Debug.LogException(t.Exception); }, TaskContinuationOptions.OnlyOnFaulted); matchRequestTask.ContinueWith(t => { Debug.Log("User cancel"); }, TaskContinuationOptions.OnlyOnCanceled); matchRequestTask.ContinueWith(t => { Debug.Log("Success"); }, TaskContinuationOptions.OnlyOnRanToCompletion); We have tested this on multiple Apple TV and network types (Wi-Fi, 5G, Ethernet), but we consistently encounter this bug along with the same log message. Could you please help us understand or resolve this issue? Thank you.
1
0
170
Apr ’25
GKMatch.chooseBestHostingPlayer(_:) always returns nil player
I'm building a game with a client-server architecture. Using GKMatch.chooseBestHostingPlayer(_:) rarely works. When I started testing it today, it worked once at the very beginning, and since then it always succeeds on one client and returns nil on the other client. I'm testing with a Mac and an iPhone. Sometimes it fails on the Mac, sometimes on the iPhone. On the device that it succeeds on, the provided host can be the device itself or the other one. I created FB9583628 in August 2021, but after the Feedback Assistant team replied that they are not able to reproduce it, the feedback never went forward. import SceneKit import GameKit #if os(macOS) typealias ViewController = NSViewController #else typealias ViewController = UIViewController #endif class GameViewController: ViewController, GKMatchmakerViewControllerDelegate, GKMatchDelegate { var match: GKMatch? var matchStarted = false override func viewDidLoad() { super.viewDidLoad() GKLocalPlayer.local.authenticateHandler = authenticate } private func authenticate(_ viewController: ViewController?, _ error: Error?) { #if os(macOS) if let viewController = viewController { presentAsSheet(viewController) } else if let error = error { print(error) } else { print("authenticated as \(GKLocalPlayer.local.gamePlayerID)") let viewController = GKMatchmakerViewController(matchRequest: defaultMatchRequest())! viewController.matchmakerDelegate = self GKDialogController.shared().present(viewController) } #else if let viewController = viewController { present(viewController, animated: true) } else if let error = error { print(error) } else { print("authenticated as \(GKLocalPlayer.local.gamePlayerID)") let viewController = GKMatchmakerViewController(matchRequest: defaultMatchRequest())! viewController.matchmakerDelegate = self present(viewController, animated: true) } #endif } private func defaultMatchRequest() -> GKMatchRequest { let request = GKMatchRequest() request.minPlayers = 2 request.maxPlayers = 2 request.defaultNumberOfPlayers = 2 request.inviteMessage = "Ciao!" return request } func matchmakerViewControllerWasCancelled(_ viewController: GKMatchmakerViewController) { print("cancelled") } func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFailWithError error: Error) { print(error) } func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFind match: GKMatch) { self.match = match match.delegate = self startMatch() } func match(_ match: GKMatch, player: GKPlayer, didChange state: GKPlayerConnectionState) { print("\(player.gamePlayerID) changed state to \(String(describing: state))") startMatch() } func startMatch() { let match = match! if matchStarted || match.expectedPlayerCount > 0 { return } print("starting match with local player \(GKLocalPlayer.local.gamePlayerID) and remote players \(match.players.map({ $0.gamePlayerID }))") match.chooseBestHostingPlayer { host in print("host is \(String(describing: host?.gamePlayerID))") } } }
4
0
392
Apr ’25
How to get GKMatch instance after accepting GKInvite?
In my SceneKit game I'm able to connect two players with GKMatchmakerViewController. Now I want to support the scenario where one of them disconnects and wants to reconnect. I tried to do this with this code: nonisolated public func match(_ match: GKMatch, player: GKPlayer, didChange state: GKPlayerConnectionState) { Task { @MainActor in switch state { case .connected: break case .disconnected, .unknown: let matchRequest = GKMatchRequest() matchRequest.recipients = [player] do { try await GKMatchmaker.shared().addPlayers(to: match, matchRequest: matchRequest) } catch { } @unknown default: break } } } nonisolated public func player(_ player: GKPlayer, didAccept invite: GKInvite) { guard let viewController = GKMatchmakerViewController(invite: invite) else { return } viewController.matchmakerDelegate = self present(viewController) } But after presenting the view controller with GKMatchmakerViewController(invite:), nothing else happens. I would expect matchmakerViewController(_:didFind:) to be called, or how would I get an instance of GKMatch? Here is the code I use to reproduce the issue, and below the reproduction steps. Code Run the attached project on an iPad and a Mac simultaneously. On both devices, tap the ship to connect to GameCenter. Create an automatched match by tapping the rightmost icon on both devices. When the two devices are matched, on iPad close the dialog and tap on the ship to disconnect from GameCenter. Wait some time until the Mac detects the disconnect and automatically sends an invitation to join again. When the notification arrives on the iPad, tap it, then tap the ship to connect to GameCenter again. The iPad receives the call player(_:didAccept:), but nothing else, so there’s no way to get a GKMatch instance again.
6
0
821
Apr ’25
Game Center save game data to iCloud
We are trying to implement saving and fetching data to and from iCloud, but it have some problems. MacOS: 15.3 Here is what I do: Enable Game Center and iCloud capbility in Signing & Capabilities, pick iCloud Documents, create and select a Container. Sample code: void SaveDataToCloud( const void* buffer, unsigned int datasize, const char* name ) { if(!GKLocalPlayer.localPlayer.authenticated) return; NSData* data = [ NSData dataWithBytes:databuffer length:datasize]; NSString* filename = [ NSString stringWithUTF8String:name ]; [[GKLocalPlayer localPlayer] saveGameData:data withName:filename completionHandler:^(GKSavedGame * _Nullable savedGame, NSError * _Nullable){ if (error != nil) { NSLog( @"SaveDataToCloud error:%@", [ error localizedDescription ] ); } }]; } void FetchCloudSavedGameData() { if ( !GKLocalPlayer.localPlayer.authenticated ) return; [ [ GKLocalPlayer localPlayer ] fetchSavedGamesWithCompletionHandler:^(NSArray<GKSavedGame *> * _Nullable savedGames, NSError * _Nullable error) { if ( error == nil ) { for ( GKSavedGame *item in savedGames ) { [ item loadDataWithCompletionHandler:^(NSData * _Nullable data, NSError * _Nullable error) { if ( error == nil ) { //handle data } else { NSLog( @"FetchCloudSavedGameData failed to load iCloud file: %@, error:%@", item.name, [ error localizedDescription ] ); } } ]; } } else { NSLog( @"FetchCloudSavedGameData error:%@", [ error localizedDescription ] ); } } ]; } Both saveGameData and fetchSavedGamesWithCompletionHandler are not reporting any error, when debugging, saveGameData completionHandler got a nil error, and can get a valid "savedGame", but when try to rebot the game and use "fetchSavedGamesWithCompletionHandler" to fetch data, we got nothing, no error reported, and the savedGames got a 0 length. From this page https://developer.apple.com/forums/thread/718541?answerId=825596022#825596022 we try to wait 30sec after authenticated , then try fetchSavedGamesWithCompletionHandler, still got the same error. Checked: Game Center and iCloud are enabled and login with the same account. iCloud have enough space to save. So what's wrong with it.
2
0
710
Mar ’25
GameKit Access Point causes camera background image in ARKit to be black in iOS 18 beta only
I have an AR game using ARKit with SceneKit that works just fine in iOS 17. In the iOS 18 betas, the AR background image shows black instead of showing the real world. As a result there's no tracking and obviously the whole game is useless. I narrowed down the issue to showing the Game Center Access Point. My app has ViewController 1 (VC1) showing the main menu and that's where I want to show the GC Access Point. From there you open VC2 which shows a list of levels. Selecting any level will open VC3 which has the ARScene. Following is the code I use to start Game Center in VC1: GKLocalPlayer.local.authenticateHandler = { gcAuthVC, error in let isGameCenterReady = (gcAuthVC == nil) && (error == nil) if let viewController = gcAuthVC { self.present (viewController, animated: true, completion: nil) } if error != nil { print(error?.localizedDescription ?? "") } if isGameCenterReady { GKAccessPoint.shared.location = .topLeading GKAccessPoint.shared.showHighlights = true GKAccessPoint.shared.isActive = true } } When switching to VC2 I run GKAccessPoint.shared.isActive = false so that the Access Point will no longer show in any of the following VCs. I tried running it in VC1, VC2, and again in VC3 - it doesn't change anything. Once I reach VC3, the background is black. If in VC1 I don't run GKAccessPoint.shared.isActive = true, so I don't activate the access point, the behavior is as follows: If I wait until after the Game Center login animation completes and closes on its own and then I proceed to VC2 and VC3, the camera image will show correctly If I quickly move to VC2 before the Game Center login animation has completed, so my code will close it by setting active = false, and then I continue to VC3, I will see the black background problem. So it does look like activating the access point and then de-activating it causes the issue. BTW, if I activate the access point and leave it on in all VCs, the same black background issue persists. Other than that, when I'm in VC3 with the black background and I switch to another app (so my game moves to the background), when it returns to the foreground, the camera suddenly shows the real world correctly! I tried to manually reset the AR session by pausing and restarting it, but that didn't change anything. Also, when I check with the debugger, it looks like when the app comes back to the foreground it also doesn't run the session start code. But something does seem to reset itself so I wonder what that is. Maybe I could trigger the same manually in my cdoe??? I repeat that everything works just fine in iOS 17 and below. This problem only started with the iOS 18 beta (currently on beta 5, but it started in some of the previous betas as well). So could this be a bug in iOS 18? As a workaround I could check the iOS version and if it's iOS18 not activate the access point, hoping that the user will not jump to VC2 too quickly, and show my own button which will open Game Center. But I'd rather give the users the full experience with their own avatar and the highlights showing up. Plus, certainly some users will move quickly to VC2 and that will be an awful experience. Any help would be greatly appreciated. Thanks!
11
2
1.1k
Mar ’25
Is there a way to get all the turnbasematches that can join
I am using Unity's GameKit to implement a turnbase game. I want to make a UI in Unity to show all the games I can join. I tried using var matches = await GKTurnBasedMatch.LoadMatches(); to get all the open matches. But it seems that I can only get the matcm related to the current apple account. Can you help me get all the matches? ALSO I used var match = await GKTurnBasedMatchmakerViewController.Request(request); to exit the gamecenter interface and start a game (automatic matching, no one was invited) Another device used var match = await GKTurnBasedMatch.Find(request); to find the game, but it did not find the game, but it start a new game (automatic matching). Can you help me solve these problems?
0
0
277
Mar ’25
Unity GameKit: signature does not match the authentication request data
I have a Unity application in which I'm implementing a GameCenter login with PlayFab. I fetch the items and use them in the PlayFab request, which returns me the error 'Authentication failed. Signature does not match the authentication request data'. I've reproduced the request using Insomnia with the same results. I have this exact same flow implemented in another application, which works normally. I'm positive that the PlayFab verification is correct, and there's indeed an issue with the data being sent, but I can't find any information about this kind of situation anywhere, and I don't know how to either reproduce the verification myself, or how to inspect the data to check for issues. I have reviewed my app's data on AppstoreConnect and have filled every form, document, and even its store page. I've also checked it's bundle identifier settings to make sure it had all the permissions necessary, which seems to be only GameCenter. I fetch the authentication items through this code try { Debug.Log("Fetching authentication items"); var fetchItemsResponse = await GKLocalPlayer.Local.FetchItems(); PlayFabGameCenterLogin(fetchItemsResponse); } catch (Exception ex) { Debug.Log("Error fetching authentication items: " + ex.Message); OnLoginFailure(); } Which is then sent to this method to start the login request static void PlayFabGameCenterLogin(GKIdentityVerificationResponse authenticationItems) { var request = new LoginWithGameCenterRequest(); request.CreateAccount = true; request.PlayerId = GKLocalPlayer.Local.GamePlayerId; request.InfoRequestParameters = new GetPlayerCombinedInfoRequestParams { GetUserAccountInfo = true }; if (authenticationItems != null) { request.PublicKeyUrl = authenticationItems.PublicKeyUrl; request.Salt = Convert.ToBase64String(authenticationItems.GetSalt()); request.Signature = Convert.ToBase64String(authenticationItems.GetSignature()); request.Timestamp = authenticationItems.Timestamp.ToString(); } else Debug.Log("Playfab Login with no authentication items"); // Login PlayFabClientAPI.LoginWithGameCenter(request, OnLoginSuccess, (e) => { I'm on Unity 2022.3.10f1 Apple.Core 3.1.3 Apple.GameKit 2.2.2 Xcode 16.2 I need information on what could be the cause of this, if it's a SDK issue, a lack of filling information somewhere, if it's some data compatibility issue (maybe data on the app that's not the same on the appstoreconnect or developer?), or if it's possible to verify the authentication data manually to investigate.
1
0
303
Mar ’25
Game Center breaks RealityView world tracking
Has anyone come across the issue that setting GKLocalPlayer.local.authenticateHandler breaks a RealityView's world tracking on iOS / iPadOS 18 beta 5? I'm in the process of upgrading my app to make use of the much appreciated RealityView unification, using RealityView not only on visionOS but now also on iOS and iPadOS. In my RealityView, I enable world tracking on iOS like this: content.camera = .worldTracking However, device position and orientation were ignored (the camera remained static) and there was no camera pass-through. Then I discovered that the issue disappeared when I remove the line GKLocalPlayer.local.authenticateHandler = { viewController, error in // ... some more code ... } So I filed FB14731139 and hope that it will be resolved before the release of iOS / iPadOS 18.
5
1
976
Mar ’25
Game Center Dashboard frequently not updating when new achievement unlocked
I am currently working on a game that involves earning achievements, which I am using the Apple Unity Plug-Ins to display. I have found that occasionally opening the Game Center Dashboard the last achievement earned will not be displayed until the game is closed and reopened. I am using GKAccessPoint.Shared.Trigger to display the Achievements screen, which occasionally seems to open a cached version of the dashboard. I've found that it seems to consistently happen when earning multiple achievements within one minute, but this is not always the case. Does anybody have any experience with something like this in the past?
1
1
1.3k
Feb ’25
GKLocalPlayer save and fetch data to iCloud issue
Hi all I have two mystic issues with saving and fetching data to and from iCloud. Both repro only after first launch of an app. 1. [GKLocalPlayer fetchSavedGamesWithCompletionHandler:] After first attempt I can see 0 saved games (but i know that there is at least one saved game) and there is no any error. In case if I try fetch one more time (without any additional actions) even immediately after first attempt I receive saved games correctly (not 0) 2. [GKLocalPlayer saveGameData: withName: completionHandler:] After first attempt I can see error The requested operation could not be completed because local player has not been authenticated. In case if I try save one more time (without any additional actions) even immediately after first attempt I can save data successfully without any error I found the same issue in StackOverflow, but there are no fixes...
4
1
1.5k
Feb ’25
GameKit Matchmaking
Hi all im having a variety of issues with gamekit matchmaking. On the simulator the matchmaking ui pops up and I can click Quick Match, then immediately "Failed to find Players" this is the same with a real Apple ID and a sandbox account. If I use real devices the app at least discovers a match, but then the match none of the delegate methods for the match ever get called and the logs are filled with socket not connected and various errors. My questions are: Should match making via quick match work in the simulator, I have seen tutorial videos etc of this working, but I can't seem to get it to work. How do people debug issues with GameCenter / Gamekit to find out why its not able to connect? Many thanks in advance
1
0
481
Feb ’25