Game Match Matching GKTurnBasedMatch has a significant lag (~ 1 min)

I am using a turn-based multiplayer game through gamecenter. I have 2 devices (1 ipad, 1 iphone) for testing in sandbox mode that worked fine, but lately it started to struggle in the process of auto-negotiation. After I sent the first turn from one user, another device does not immediately recognize this game, but opens its new fresh game. Before he could immediately notice the game running on another device, and the match-match was pretty simple. And I don’t remember changing any details related to matchmaking ( NSCoding , GKTurnBasedEventHandler , GKTurnBasedMatchmakerViewControllerDelegate delegate methods, etc.).

Now I'm sending the first turn from one device and should wait about 1 minute so that the other device can successfully connect to this game. After connecting, endTurnWithMatchData causes work without any problems, it can send and receive data within 1-2 seconds. But it will not be a good UX if users start a new game and have to wait 1 minute so that another user can connect to their game. Has anyone experienced a significant lag in the auto-negotiation process? I have not yet implemented the invitation, so I cannot verify it. The mapping files I archived with NSKeyedArchiver seemed rather large, 3396 bytes, even for a new game with almost no data. And here are the relevant parts of my code:

GameOptionsViewController :

 - (void)turnBasedMatchmakerViewControllerWasCancelled:(GKTurnBasedMatchmakerViewController *)viewController { [self dismissViewControllerAnimated:YES completion:nil]; } - (void)turnBasedMatchmakerViewController:(GKTurnBasedMatchmakerViewController *)viewController didFailWithError:(NSError *)error { [self dismissViewControllerAnimated:YES completion:nil]; } - (void)turnBasedMatchmakerViewController:(GKTurnBasedMatchmakerViewController *)viewController didFindMatch:(GKTurnBasedMatch *)match { [self dismissViewControllerAnimated:NO completion:nil]; self.gcMatch = match; [self performSegueWithIdentifier:@"GameMultiplayer" sender:self]; } - (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if([segue.identifier isEqualToString:@"GameMultiplayer"]) { GameViewController *GameVC = (GameViewController *)segue.destinationViewController; [GameVC setGameMode:GAMEMODE_MULTIPLAYER_SAMEDEVICE]; //Multiplayer game it is if(self.gcMatch != nil) { [GameVC setGameMode:GAMEMODE_MULTIPLAYER_GAMECENTER]; GameVC.gcMatchDelegate = self; GameVC.gcMatch = self.gcMatch; NSLog(@"Game OVC Segue: Match ID | %@", self.gcMatch.matchID); } } else { ... } } 

GameViewController :

 //This method is called according to user actions //It the only method I use to send data to other participant -(void) sendCurrentGameDataWithNewTurn:(BOOL) newTurn { NSLog(@"Sending game data current participant : %@", gcMatch.currentParticipant.playerID); //Update match data if it is corrupted anyhow if (gcMatch.currentParticipant == nil) { [GKTurnBasedMatch loadMatchWithID:gcMatch.matchID withCompletionHandler:^(GKTurnBasedMatch *match, NSError *error) { if (error != nil) { NSLog(@"Error :%@", error); return ; } [self sendCurrentGameDataWithNewTurn:newTurn]; }]; } else { NSData *matchData = [NSKeyedArchiver archivedDataWithRootObject:game]; //Game advances to new player, buttons are disabled if(newTurn) { NSLog(@"SENDING NEW TURN"); NSUInteger currentIndex = [gcMatch.participants indexOfObject:gcMatch.currentParticipant]; GKTurnBasedParticipant *nextParticipant; nextParticipant = [gcMatch.participants objectAtIndex: ((currentIndex + 1) % [gcMatch.participants count])]; [gcMatch endTurnWithNextParticipants:[NSArray arrayWithObject:nextParticipant] turnTimeout:GC_TURN_TIMEOUT matchData:matchData completionHandler:^(NSError *error) { NSLog(@"Sent"); if (error) { NSLog(@"SNT - %@", error); } }]; } else { NSLog(@"ONLY UPDATING DATA"); [gcMatch saveCurrentTurnWithMatchData:matchData completionHandler:^(NSError *error) { NSLog(@"Sent"); if (error) { NSLog(@"OUD - %@", error); } }]; } } 

}

 -(void) updateGameDataWithGCMatch { //Update whole game data self.game = [NSKeyedUnarchiver unarchiveObjectWithData:self.gcMatch.matchData]; //Update game ui ... } -(void) handleTurnEventForMatch:(GKTurnBasedMatch *)match didBecomeActive:(BOOL)didBecomeActive { //Check if I got data for the currently active match that options vc forwarded me here, if not do some debug print and return if(![self.gcMatch.matchID isEqual:match.matchID]) { //For debugging reasons I skip if i get info for any previous match (other player quit etc) NSLog(@"GCMatch matchID: %@ match matchID: %@",self.gcMatch.matchID,match.matchID); return; } NSLog(@"Turn event handle"); self.gcMatch = match; if([match.currentParticipant.playerID isEqualToString: [GKLocalPlayer localPlayer].playerID ]) { //Disable field buttons [self setFieldButtonsEnabled:TRUE]; [self turnChangeAnimationFromLeftToRight:FALSE]; } [self updateGameDataWithGCMatch]; } 
+6
source share
1 answer

Regarding your question:

I myself was tempered with matchmaking over the Game Center quite a bit, and also experienced delays quite often, which, as proved, were not caused by my site, but by the servers of the Apple game centers.

Regarding additional guidance:

As far as I understand, your current approach to creating partnerships on the device:

See if there is a match that I can connect with β†’ If YES requests gamedata and connects to an ELSE match, start your own match and pass matchdata p>

In my experience, it’s best to start with matchrequestbroadcasts, wait until you find a second player, identify the server device (for example, a lower checksum of the name of the game center), and then run the game on this device.

0
source

All Articles