GameKit: 'didFind match' never called

I am trying to implement a real-time match in GameCenter using GameKit and SpriteKit.

This is my scene:

Code Block
class IntroScene: SKScene, GameCenterManagerDelegate {
var gameCenterManager: GameCenterManager?
override func didMove(to view: SKView) {
GameCenterManager.manager.delegate = self
<other code>
}
override func didChangeSize(_ oldSize: CGSize) {
super.didChangeSize(oldSize)
GameCenterManager.manager.authenticatePlayer()
}
func didChangeAuthStatus(isAuthenticated: Bool) {
...Enabling the Button to play in GameCenter
}
func presentGameCenterAuth(viewController: UIViewController?) {
guard let vc = viewController else {return}
self.view!.window?.rootViewController?.present(vc, animated: true)
}
func presentMatchmaking(viewController: UIViewController?) {
guard let vc = viewController else {return}
self.view!.window?.rootViewController?.present(vc, animated: true)
}
->> Problem here. Never gets called
func presentGame(match: GKMatch) {
print("....INTROSCENE: DELEGATE PRESENT_GAME CALLED......")
... Presenting a new scene
}
}


This is my GameCenterManager class:

Code Block
final class GameCenterManager : NSObject, GKLocalPlayerListener {
  static let manager = GameCenterManager()
  weak var delegate: GameCenterManagerDelegate?
  var maxPlayers = 2
  var match: GKMatch?
  static var isAuthenticated: Bool {
    return GKLocalPlayer.local.isAuthenticated
  }
   
  override init() {
    super.init()
  }
   
   
  func authenticatePlayer() {
    GKLocalPlayer.local.authenticateHandler = { gcAuthVC, error in
      self.delegate?.didChangeAuthStatus(isAuthenticated: GKLocalPlayer.local.isAuthenticated)
      if GKLocalPlayer.local.isAuthenticated {
        GKLocalPlayer.local.register(self)
      }
      // If the User needs to sign to the Game Center
      else if let vc = gcAuthVC {
        self.delegate?.presentGameCenterAuth(viewController: vc)
      }
      else {
        print(">>>>> Error authenticating the Player! \(error?.localizedDescription ?? "none") <<<<<")
      }
    }
  }
   
  func presentMatchmaker() {
    guard GKLocalPlayer.local.isAuthenticated else { return }
    let request = GKMatchRequest()
    request.minPlayers = 2
    request.maxPlayers = 6
    request.inviteMessage = "Would you like to play?"
    guard let vc = GKMatchmakerViewController(matchRequest: request) else { return }
    vc.matchmakerDelegate = self
    delegate?.presentMatchmaking(viewController: vc)
  }
   
// THIS IS WORKING...
  func player(_ player: GKPlayer, didAccept invite: GKInvite) {
     
    print("-----player -- did accept invite-------\(player.displayName)")
     
    guard let vc = GKMatchmakerViewController(invite: invite) else { return }
    vc.matchmakerDelegate = self
     
    self.gameCenterViewController?.present(vc, animated: true, completion: nil)
  }
   
  func player(_ player: GKPlayer, didRequestMatchWithRecipients recipientPlayers: [GKPlayer]) {
    print("didRequestMatchWithRecipients")
  }
   
   
  func player(_ player: GKPlayer, matchEnded match: GKTurnBasedMatch) {
    print("match ended")
  }
   
  func player(_ player: GKPlayer, wantsToQuitMatch match: GKTurnBasedMatch) {
    print("wants to quit match")
  }
}
extension GameCenterManager: GKMatchmakerViewControllerDelegate {
   
// THIS IS NOT WORKING -(
  func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFind match: GKMatch) {
     
    print("-----matchmakerVC did find match-------")
     
    viewController.dismiss(animated: true)
     
    match.delegate = self
     
    delegate?.presentGame(match: match)
  }
   
  func matchmakerViewControllerWasCancelled(_ viewController: GKMatchmakerViewController) {
    print("matchmakerVC was cancelled")
    viewController.dismiss(animated: true)
    delegate?.matchmakingCancelled()
  }
   
  func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFailWithError error: Error) {
    viewController.dismiss(animated: true)
    delegate?.matchmakingError(error: error)
  }
}
extension GameCenterManager: GKMatchDelegate {
   
  func match(_ match: GKMatch, didReceive data: Data, forRecipient recipient: GKPlayer, fromRemotePlayer player: GKPlayer) {
    // HANDLE DATA
  }
   
  func match(_ match: GKMatch, didReceive data: Data, fromRemotePlayer player: GKPlayer) {
    //HANDLE DATA
  }
   
   
  func match(_ match: GKMatch, player: GKPlayer, didChange state: GKPlayerConnectionState) {
    print("-----match did change state")
    guard match == self.match else { return }
    switch state {
    case .connected where self.match != nil :
      print("-----MATCH DID CHANGE STATE CONNECTED-----")
    case .disconnected:
      print("-----MATCH DID CHANGE STATE DISCONNECTED-----")
    default:
      break
    }
  }
   
  func match(_ match: GKMatch, didFailWithError error: Error?) {
    print("-----match did fail with error")
  }
}


So, basically this is what happens.
  • Player 1 starts the game. The player gets successfully authenticated.

  • I invite Player 2 to join the game. The invitation is sent to Player 2's device.

  • Player 2 accepts the game (printing player did accept invite).

However, after that nothing happens. There is continuing spinning wheel saying "Sending" on Player 1's device, and the game scene never launches. I never receive notification that the match has been found, i.e. matchmakerViewController(_ viewController:,match:) is never called.

Any help would be greatly appreciated!

Replies

Did you ever figure this out? I'm having a very similar issue except I can't even get the player:didAccept to happen on player 2's device....
I figured out the issue. I was not registering my GKLocalPlayerListener with the GKLocalPlayer register function (https://developer.apple.com/documentation/gamekit/gklocalplayer/1515393-register).

I also posted a suggestion to Apple's feedback to update the documentation with this information (https://developer.apple.com/documentation/gamekit/finding_multiple_players_for_a_game).