Hi there,
With a couple of other developers we have been busy with migrating our SpriteKit games and frameworks to Swift 6.
There is one issue we are unable to resolve, and this involves the interaction between SpriteKit and GameplayKit.
There is a very small demo repo created that clearly demonstrates the issue. It can be found here:
https://github.com/AchrafKassioui/GameplayKitExplorer/blob/main/GameplayKitExplorer/Basic.swift
The relevant code also pasted here:
import SwiftUI
import SpriteKit
struct BasicView: View {
var body: some View {
SpriteView(scene: BasicScene())
.ignoresSafeArea()
}
}
#Preview {
BasicView()
}
class BasicScene: SKScene {
override func didMove(to view: SKView) {
size = view.bounds.size
anchorPoint = CGPoint(x: 0.5, y: 0.5)
backgroundColor = .gray
view.isMultipleTouchEnabled = true
let entity = BasicEntity(color: .systemYellow, size: CGSize(width: 100, height: 100))
if let renderComponent = entity.component(ofType: BasicRenderComponent.self) {
addChild(renderComponent.sprite)
}
}
}
@MainActor
class BasicEntity: GKEntity {
init(color: SKColor, size: CGSize) {
super.init()
let renderComponent = BasicRenderComponent(color: color, size: size)
addComponent(renderComponent)
let animationComponent = BasicAnimationComponent()
addComponent(animationComponent)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
@MainActor
class BasicRenderComponent: GKComponent {
let sprite: SKSpriteNode
init(color: SKColor, size: CGSize) {
self.sprite = SKSpriteNode(texture: nil, color: color, size: size)
super.init()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class BasicAnimationComponent: GKComponent {
let action1 = SKAction.scale(to: 1.3, duration: 0.07)
let action2 = SKAction.scale(to: 1, duration: 0.15)
override init() {
super.init()
}
override func didAddToEntity() {
if let renderComponent = entity?.component(ofType: BasicRenderComponent.self) {
renderComponent.sprite.run(SKAction.repeatForever(SKAction.sequence([action1, action2])))
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
As SKNode is designed to run on the MainActor, the BasicRenderComponent is attributed with MainActor as well. This is needed as this GKComponent is dedicated to encapsulate the node that is rendered to the scene.
There is also a BasicAnimationComponent, this GKComponent is responsible for animating the rendered node.
Obviously, this is just an example, but when using GameplayKit in combination with SpriteKit it is very common that a GKComponent instance manipulates an SKNode referenced from another GKComponent instance, often done via open func update(deltaTime seconds: TimeInterval) or as in this example, inside didAddToEntity.
Now, the problem is that in the above example (but the same goes foupdate(deltaTime seconds: TimeInterval) the methoddidAddToEntity is not isolated to the MainActor, as GKComponent is not either.
This leads to the error Call to main actor-isolated instance method 'run' in a synchronous nonisolated context, as indeed the compiler can not infer that didAddToEntity is isolated to the MainActor.
Marking BasicAnimationComponent as @MainActor does not help, as this isolation is not propogated back to the superclass inherited methods.
In fact, we tried a plethora of other options, but none resolved this issue.
How should we proceed with this? As of now, this is really holding us back migrating to Swift 6. Hope someone is able to help out here!
GameKit
RSS for tagCreate apps that allow players to interact with each other using GameKit.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hi,
I tried to save the game progress using the official Apple plugin for Unity but the crash happened when I active the "iCloud Documents" inside capabilities and when deactivated it this error message appeared:
Code=27 Domain=GKErrorDomain Description=The requested operation could not be completed because you are not signed in to iCloud or have not enabled iCloud Drive. (UbiquityContainerUnavailable)
Authentication with Game Center works fine using the Core plugin, but nothing works correctly when I use the GameKit plugin.
Note:
I already active iCloud for app Identifier.
Tichnecal informations:
Unity version: 2022.3.47f1 LTS
XCode 16
Swift 6
GameKit-3.0.0 (Apply unity plugin)
Core-3.1.5 (Apply unity plugin)
After running build.py -p Core GameKit and adding the tar balls to the Unity project in Assets/ExternalPackages no packages seem to be found when running the build using our continuous integration system.
This was not the case when the project was opened in the Editor.
It looks like in Apple.Core, the ApplePluginEnvironment hasn't run the OnEditorUpdate function and so the _appleUnityPackages Dictionary is empty.
A change to ApplePlugInEnvironment.cs seemed to fix the issue:
public static AppleNativeLibrary GetLibrary(string packageDisplayName, string appleBuildConfig, string applePlatform)
{
// ?FIX?: If we're not in the editor, we might not have updated the package list.
if (_appleUnityPackages.Count == 0 && _updateState == UpdateState.Initializing)
{
OnEditorUpdate(); // UpdateState.Initializing
OnEditorUpdate(); // UpdateState.Updating
}
I'm not sure if this is something we're doing incorrectly, the documentation for the plug-in mostly covered building the package.
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.
Hi I have attempted to find a fix for my issue via documentation online and one phone support ( not code level support ) call to no end. I could continue to try various things but would like to see if someone else has encountered this issue and a fix for it.
Background: My Game app is live on App Store and has 1 classic leaderboard . I am now getting ready to submit an update to the app and it also entails adding a new recurring leaderboard. I added the leaderboard in App Store. I however have NOT uploaded my new build yet. I have also not added my leaderboards ( currently live and not live ) to any set.
When I try to submit scores using
GKLeaderboard.submitScore(_:context:player:leaderboardIDs:completionHandler:) to the new non-live leaderboard it works ( gives me no error )
When I try to load the scores from the new non-live leaderboard
GKLeaderboard.loadLeaderboards(IDs:completionHandler:)
loadEntries(for:timeScope:range:completionHandler:)
it fails. Error: "leaderboardID not found"
I could try ( and will )
uploading the new build to AppStore connect and associating the new leaderboard to it before testing again.
try associating each leaderboard to a set
Is there anything else that I should be aware of ?
Thanks in advance
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 player, the native Game Center interface opens and begins the matchmaking process.
Almost immediately, 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, the task does not complete when the log appears (our Debug.Log are nerver called).
But if we manually cancel the matchmaking process, the "User cancel" log is correctly triggered.
Here is a code snippet for the request :
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.LogInfo("User cancel"); }, TaskContinuationOptions.OnlyOnCanceled);
matchRequestTask.ContinueWith(t => { Debug.LogInfo("Success"); }, TaskContinuationOptions.OnlyOnRanToCompletion);
We have tested this on multiple devices 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.
When testing my development build for gamecenter authentication, the game crashes. I've breadcrumbed it to the "await GKLocalPlayer.Authenticate();" call. Can't find any documentation on this issue and have been looking through the forums!
I've already done all of the usual stuff like verifying bundle identifiers match, ensuring game center is enabled for the app, setting up app store connect, using a sandbox account, etc...
Please point me to some resources if you know any. Any help is appreciated, I'm starting to lose hope here!
New to achievements. I added them in App Store Connect and want to test them.
Apple Documentation says this:
"Before you begin testing your GameKit configuration, you need to enable Debug Mode. In Xcode, choose Product > Scheme > Edit Scheme. From the Run configuration, select Options and toggle Enable Debug Mode.
To begin testing your achievement configuration, open the game Progress Manager. In Xcode, choose Debug > GameKit > Manage Game Progress."
Sounds easy enough, but there is no "GameKit" under Debug in Xcode 16.2.
Topic:
Graphics & Games
SubTopic:
GameKit
I work on a team that provides an SDK for another game to handle various tasks like authentication. They are experiencing a case where devices using iOS 17 are failing to authenticate with GameCenter, receiving the message "The requested operation could not be completed because local player has not been authenticated." We imagine this is because they still have some setup to finish regarding GameCenter itself, and we're working with them to take care of that.
However, on iOS 18, their app ends up waiting indefinitely for GameCenter authentication messages that it never receives. That's where we're puzzled. We expect them to have the same outcome regardless of OS version.
We initiate GameCenter authentication by setting an authenticateHandler after some initial application setup. The handler has code to account for UI, errors, and successful authentication.
On iOS 17, it's clear that it's getting called as expected because they receive an indication that the player isn't authenticated. But on iOS 18, it looks like the same handler code on iOS 18 isn't being called at all. Are there differences in how iOS 18 interacts with the authenticationHandler that we somehow aren't accounting for? Or is there potentially something else that we're doing incorrectly that is manifesting only on iOS 18?
Here's a simplified version of our login function code (in Obj-C++). There is no OS-specific code, and the job that owns this function does stay in scope until after authentication is complete.
void beginLogin()
{
// Snip: Check if the user is already logged in.
// Snip: Prevent multiple concurrent calls to this function.
auto authenticateHandler = ^(UIViewController* gcViewController, NSError* error)
{
if (gcViewController != nil)
{
// Snip: Display the UI
}
else if (error != nil)
{
// Snip: Handle the error.
}
else
{
if ([[GKLocalPlayer localPlayer] isAuthenticated])
{
// Snip: Handle successful authentication.
}
else
{
// Snip: Handle other case.
}
}
};
[[GKLocalPlayer localPlayer] setAuthenticateHandler: authenticateHandler];
}
Hey all — I’ve been building out my first set of Game Center Achievements for a game I’m working on, and I’ve run into something odd with the image quality.
The specs say to upload icons at 512x512 or 1024x1024@2x. I’ve been uploading 1024x1024 PNGs (without explicitly naming them “@2x” since there’s only one upload slot), assuming that Game Center would just handle the scaling automatically — kind of like how a lot of things are getting more streamlined across platforms lately.
But in testing, the icons are showing up a bit blurry, especially in the Game Center interface. It’s not horrible, but it’s definitely softer than I expected — more like low-res than Retina.
All my test devices (outside the Simulator) are running iOS 26, so I’m also wondering if this might be a beta-related display bug?
Has anyone else run into this? Curious if I’m missing a best practice here, or if I really do need to ensure I’m uploading it with the @2x suffix, or maybe something else entirely?
Thanks!
On an iPad running iPadOS 26 beta 4, when tapping the Game Center Access Point, the overlay doesn’t show the configured achievements, leaderboards or challenges.
I should specify this is an in-development app and the achievements and leaderboards are in the “Not Live” state, however they show on other devices running iOS 18 in the Access Point UI.
Anyone else having this issue? If so, how should I test achievements and leaderboards while iOS 26 beta is out?
The UI looks like this on iPadOS 26:
Hello — I shipped an App Store build that signs in to Game Center using the Apple Unity Plugins (GameKit). The login banner appears, but my app still doesn’t show up in Game Center’s “All activity” (You started playing *** 2d ago)
What I’ve done
Call await GKLocalPlayer.Authenticate();
“Game Center” is enabled for the current version in App Store Connect
Confirmed: other App Store games do appear under “All Activity” on the same device/account
Timeline: This is the first version that enables Game Center (not the app’s first release), and it has been about 2 hours since this build went live.
Questions
Is authentication alone sufficient for “Recently Played,” or is at least one Game Center component (leaderboards, achievements, activities, multiplayer) required?
Is there a typical propagation delay before “Recently Played” starts showing a newly enabled app/version?
Is there anything else I should configure in App Store Connect or entitlements to make “Recently Played” visible?
Thanks for any help.
I’m running into unexpected problems with the Unity GameKit plugin setup with the new Activities. I didn’t see anyone else mentioning these issues, so my guess is that it’s a problem with my setup.
The authentication (GKLocalPlayer.Authenticate()) works as expected, but any call to the new GameActivity functionality (e.g. GKGameActivityDefinition.LoadGameActivityDefinitions() or GKGameActivity.WantsToPlay) gives me an exception with a 'UnsupportedOperationForOSVersion' reason despite it running on an iOS 18.6.1 device.
I’m using a completely empty Unity 2022.3.62f1 project that only contains the official authentication example, followed by an event handler for activities from another example and the Unity core and gamekit plugins.
The setup:
macOS 15.6
Xcode 26 beta 6 (also tried with 5)
Physical iPhone device running iOS 18.6.1
Unity 2022.3.62f1, which satisfies the requirements
Unity plugin, Xcode setup, and build steps:
I Followed the official beta branch build steps for Unity plugins with python3 build.py -m iOS iPhoneSimulator macOS -p Core GameKit which ran through after a slight modification for the macOS target that somehow contained an unknown team reference for the GameKitWrapper project, which I changed to not reference a team and use ‘sign to run locally’, as was the case for the other packages. As far as I understood the macOS version is not strictly necessary either way just for running it on a local iOS device(?)
I Imported these as tarball packages into the empty Unity 2022.3.62f1 project as per the official instructions, which seems to work as expected
Added a single script with the mentioned example code added in a MonoBehavior.Start
Building in Unity works as expected as well, creating the Xcode project
The Unity-iPhone target has the GameKit framework linked (’do not embed’) and the GameCenter capability was added automatically as expected
The GameKit framework seems to not be added to the UnityFramework target, but I don’t think this is necessary? Quickly testing this with the GameKit framework added there as well didn’t make a difference
The linked GameKit framework is indeed the expected Xcode 26 beta version
I can then build and run this on the physical iPhone iOS 18.6.1 device, where I get an ‘UnsupportedOperationForOSVersion’ as soon as I try to subscribe to deeplinking events (GKGameActivity.WantsToPlay) or use other GameKit Activity functionality from the official examples:
// log showing that it's actually running on iOS 18.6:
[Apple.Core Plug-In Runtime] Availability Runtime Environment: iOS 18.6
Apple.Core.Availability:OnApplicationStart()
// and the exception I get:
GameKitException: Code=-7 Domain=GKErrorDomain Description=The operation couldn’t be completed. (GKErrorDomain error -7.) (UnsupportedOperationForOSVersion)
at Apple.GameKit.DefaultNSErrorHandler.ThrowNSError (System.IntPtr nsErrorPtr) [0x00000] in <00000000000000000000000000000000>:0
Rethrow as TypeInitializationException: The type initializer for 'Apple.GameKit.GKGameActivity' threw an exception.
I unfortunately didn’t find any clues as to why this happens and how to resolve it on this forum or otherwise.
Changing the minimum iOS version - up to 18.6 from the previously used (Unity export default) 12.0 for any and all targets - did not yield a different result
I'd rather not update the phone to use the iOS 26 beta, though as far as I understood this is not necessary
Any pointers to what I might be missing or doing wrong are greatly appreciated!
Thank you very much in advance!
Hi,
Since iOS 26 introduced the new Games app, I’ve noticed a problem when using a Nintendo Switch Pro Controller in wired USB-C mode, and also with third-party controllers that emulate it (like the GameSir X5 Lite).
In the Games app interface, only the L/R buttons respond, but the D-Pad and analog sticks don’t work at all. Once inside actual games, the controller works fine — the issue only affects the Games app UI.
What I’ve tested so far:
Xbox / PlayStation controllers → work fine in both wired and Bluetooth, including inside the Games app.
Switch Pro Controller (Bluetooth) → works fine, including in the Games app.
Switch Pro Controller (wired) → same issue as the X5 Lite, D-Pad and sticks don’t work in the Games app.
This makes it hard to use the new Games app launcher with these controllers, even though they work perfectly once a game is launched.
My question: is this an iOS bug (Apple needs to add proper support for wired Switch Pro controllers in the Games app), or something that Nintendo / GameSir would need to address?
Thanks in advance to anyone who can confirm this or provide more info.
Hello -
Upon enabling debug mode for GameKit configuration for my iOS app, I do not see any devices (my iPhone or simulators) in the device list within the "Manage Game Progress" debug tool. I only see my Mac as a device. Is there any trick to this or a way to add devices to this list?
Thank you
I have created a turn based game using GameKit. Everything is pretty much done, last thing left to do is the turn time out.
I am passing GKTurnTimeoutDefault into the timeout argument in:
func endTurn(withNextParticipants nextParticipants: [GKTurnBasedParticipant], turnTimeout timeout: TimeInterval, match matchData: Data)
However when I check the .timeoutDate property of the GKTurnBasedParticipant participants, the value is always nil.
What am I doing wrong? Am I checking the right property or is there another one instead that I don't know about? I have tried passing different values to the timeout parameter but the timeoutDate is always nil.
Has anyone successfully implemented a timeout using GKTurnBasedMatch ?
Topic:
Graphics & Games
SubTopic:
GameKit
Leaderboard has not worked for past two days. What’s up with that?
Topic:
Graphics & Games
SubTopic:
GameKit
Updated to GPT 2 with the app format and whisky in October. I'm using steam in GPT to play the windows only games. The games consistently crash my computer to restart when I played games like Liar's Bar and Phasmophobia, the latter even with its performance optimization update released today. Both of them do that when I load into the game room, so the bar/ghost house or even while loading. It ran Outpath properly though, which was something with much lower quality than LB and Phas. I don't think it's a simple RAM config issue because Phasmophobia ran fine for me with older versions in GPT 1 although I did experience occasional crashes but I think those were only crashing the game not my mac. I'm not sure what I'm doing wrong that I can't run those games or if it's a GPT problem. I'm using a MPB Pro M1 with 16GB memory on Sequoia 15.0.1.
Topic:
Graphics & Games
SubTopic:
GameKit
GKGameCenterViewController won't turn off.
With Core and GameKit from GitHub apple/unityplugins,
I succeeded in logging in and displaying GKGameCenterViewController.
Other leaderboards and everything work fine, but when I press X on GameCenter to return to the game, nothing happens.
I tried debugging by printing logs here and there in the plugin to check, but I didn't get any results.
When I press X, I couldn't get any logs or responses. It was like a button with no listener attached. No, it was more like an image.
Based on the community posts that said it worked fine before, it seems that the recent GameCenter update was not applied to the plugin, was omitted, or changed, causing a mismatch.
Hi,
I have a test app with a single "game centre achievement" and I am running it on my iPad and unable to list that achievement with
GameCenterManager.shared.loadAchievements
The app is still in version 1.0, prepare for submission status, (it is not ready for review submission). Game Center entitlement is added for the app and the achievement is added to the Game Center section of app. However it is marked as NotLive.
I am using a sandbox account to login to game centre on the iPad and I can't fetch this achievement. Is it because it is "NotLive". ? How do I test my Game Center achivement on the device without releasing it yet.
Topic:
Graphics & Games
SubTopic:
GameKit