Skip to Content
Course content

215: Building a Multiplayer Game Lobby with GameKit

Click on the "Edit" button in the top corner of the screen to edit your slide content.

How do I actually get players to find each other without manual IDs?

If you're building something like our "Galactic Arena" space shooter, you don't want your players swapping alphanumeric codes over text messages just to play a match. That's a UX nightmare. The easiest way to handle this is using GKMatchmakerViewController. It's essentially a pre-built lobby UI provided by Apple that handles the heavy lifting of searching for opponents and sending invitations.

I usually recommend starting here because it lets you verify your networking logic before you spend three days polishing a custom lobby UI. You just tell it how many players you need, and GameKit handles the matchmaking queue.

let matchmaker = GKMatchmakerViewController(
    matchmaker: GKMatchmaker(), 
    gameKitMatchmakerDelegate: self
)
present(matchmaker, animated: true)

One thing to keep in mind: make sure you've actually enabled Game Center in your project's Capabilities tab, or this view controller will just spin forever and leave you wondering why nothing is happening.

What happens once a match is found, and how do I keep track of it?

Once the matchmaking process succeeds, GameKit calls your delegate method. This is the critical moment where you transition from "searching" to "connected." The most important thing you need to do here is capture the GKMatch object. Think of the GKMatch as your persistent pipe to the other players; if you let this object go out of scope, you've effectively hung up the phone on your opponents.

Here is how I typically handle the hand-off in the delegate:

func matchmaker(_ matchmaker: GKMatchmaker, didFind match: GKMatch) {
    // Store this globally or in a GameSession manager
    self.currentMatch = match 
    
    // You also need to tell GameKit you're ready to send/receive data
    self.currentMatch?.delegate = self 
    
    print("We've got a match! Ready to launch the Arena.")
}

I've seen a lot of developers forget to set the match.delegate. If you miss that step, your didReceiveData methods will never fire, and you'll spend an hour debugging a "connection" that is actually just a one-way street.

How do I actually send "Ready" signals or chat messages in the lobby?

Now that you have your GKMatch object, you can send data. But here is the catch: GameKit doesn't care what your data looks like. It just sends Data blobs. You'll need to encode your lobby messages—like "Player 1 is Ready"—into a format like JSON or a simple Enum using Codable.

For lobby actions, you always want to use reliable transmission. You don't want a "Start Game" packet to vanish into the ether because of a momentary Wi-Fi hiccup.

struct LobbyMessage: Codable {
    let action: String
    let playerID: String
}

func sendReadySignal() {
    let message = LobbyMessage(action: "READY", playerID: "AcePilot_99")
    if let data = try? JSONEncoder().encode(message) {
        try? currentMatch?.sendData(toAllPlayers: data, dataMode: .reliable)
    }
}

On the receiving end, you'll implement match(_:didReceiveData:fromPlayer:dataMode:). I suggest using a switch statement on the decoded action string to trigger different UI updates in your lobby, like checking off a "Ready" box next to a teammate's name.




📋 Practical Task

Implement the Galactic Arena Lobby Handshake

Build a small prototype that implements the GKMatchmakerDelegate and GKMatchDelegate. Your goal is to create a "Handshake" system: when a match is found, the player who is designated as the "Host" (the player with the lowest GKPlayer ID) must send a "Welcome" data packet to all other players. The other players must respond with a "Joined" packet. Log these exchanges to the console to verify that the reliable data pipeline is functioning correctly before the game scene loads.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.