I am currently working on my game and I have decided to enable multiplayer via GameCenter in the Game to allow users to play their friend. I have followed a tutorial by RayWinderLinch, but ran into a problem.
My problem is that when I load up the GKMatchMakingViewController
and hit the big Play Now
button on both devices it will find each other (which is meant to happen) and under the set game center user name it will say Ready
.
This means that GameCenter has found each player and is ready to start the match which it should, but in my case the match never begins. It is stuck on a loop that says Starting Game...
and nothing happens. It appears that the
func matchmakerViewController(viewController: GKMatchmakerViewController!, didFindMatch theMatch: GKMatch!)
and the
func match(theMatch: GKMatch!, player playerID: String!, didChangeState state: GKPlayerConnectionState)
method's are never ran. I am completely lost on what is going on. I have tried this many times over and over to fix the problem but nothing worked. I will attach an image that show's the screen of the application where my problem persists and I will also attach the code I am using.
I am using a framework based of of the
GameKitHelper.h
In the mentioned tutorial above. It is written in swift and is called GCHelper
Code
The code for GCHelper can be found using the GitHub link mention earlier
I have cut out code that is unnecessary for this problem
class GameScene : SKScene, GameKitHelper, MultiplayerNetworkingProtocol {
override func didMoveToView () {
GCHelper().authenticateLocalUser() //Authenticate GameCenter User
println("\n \n \n Authenticating local user \n \n \n")
}
func startMultiplayer () {
var vc = self.view?.window?.rootViewController
GameKitHelper().findMatchWithMinPlayers(2, maxPlayers: 2, viewController: vc!, delegate: self); //Find match and load GKMatchMakerViewController
}
func matchStarted() {
//Delegate method
println("match started")
}
func matchEnded() {
//Delegate method
println("match ended")
}
func match(match: GKMatch, didReceiveData: NSData, fromPlayer: String){
//Delegate Method
println("Did receive data")
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch in (touches as! Set<UITouch>) {
let location = touch.locationInNode(self)
if self.nodeAtPoint(location) == multiplayer //SKSpriteNode {
//User clicked on multiplayer button, launch multiplayer now!
println("Loading multiplayer")
startMultiplayer()
}
}
Image
UPDATE
I have noticed that when I test using my iPhone and the simulator, on the iPhone the status will go from Ready
to Disconnected
but on the simulator the status is still Ready
and then I will get the following message in the console for the iPhone
Warning matchmakerViewController:didFindMatch: delegate method not implemented`
Even though it is implemented in the GCHelper.swift
file. This does not happen when I test on my iPhone and iPad Mini it just keeps on saying Starting Game...
Any help will be appreciated.
authenticationChanged
in GCHelper.swift
must not be private
. You may have to remove that keyword.There are a few delegates involved, and in your example, there are a few competing protocols. My recommendation is to create a new App using minimalistic code to track down the startMultiplayer
issue.
Create a new project (Xcode > File > New > Project... > Single View Application > ... > Create) using the very same Product Name & Organization Name as your game, so that it matches both App Bundle Identifier and iTunes Game Center parameters. This will allow you to run tests without overhead.
Use this Podfile:
platform :ios, '8.0'
use_frameworks!
target 'SO-31699439' do
pod 'GCHelper'
end
Use a GCHelperDelegate
Create a UIViewController
with just the bare minimum (a Start Multiplayer button), and connect it to this action:
@IBAction func startMultiplayerAction(_ sender: AnyObject) {
GCHelper.sharedInstance.findMatchWithMinPlayers(
2,
maxPlayers: 2,
viewController: self,
delegate: self);
}
Here is the crux: the delegate you pass must adopt GCHelperDelegate
. It does not have to be the same class, but in your example above it is, and the present rule was not respected. For this example, ViewController
adopts GCHelperDelegate
:
import UIKit
import GCHelper
import GameKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
GCHelper.sharedInstance.authenticateLocalUser()
}
}
Implement required GCHelperDelegate methods in an extension
Since ViewController
adopts GCHelperDelegate
, the three methods below must be in that same class, and will be invoked:
extension ViewController: GCHelperDelegate {
func matchStarted() {
print("matchStarted")
}
func match(_ match: GKMatch, didReceiveData: Data, fromPlayer: String) {
print("match:\(match) didReceiveData: fromPlayer:\(fromPlayer)")
}
func matchEnded() {
print("matchEnded")
}
}
Tested: built, linked, ran, successful match.
Launch app, tap Start Multiplayer button, tap Play Now on both devices (or iPhone Simulator + real device).
Log:
Authenticating local user...
Authentication changed: player not authenticated
Ready to start match!
Found player: SandboxPlayer
matchStarted
► Find this solution on GitHub and additional details on Swift Recipes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With