Matchmaking Plugin #

The Matchmaking Plugin provides the following methods that allow for a wide variety of matchmaking implementations:

initializeHandles initial steps for parties that enter the Matchmaking service.
matchPartiesAttempts to match an anchor Matchable with another Matchable in the queue. If a match is made, a NewGameInstance is returned.
buildMatchAttempts to match an Active Match with another Matchable in the matchmaking service.
endOfLoopReturns a NewGameInstance or null at end of the matchmaking loop to either create a new game instance with the anchor Matchable, or exit the matchmaking process.

Initializing the matchmaking process #

At this stage of the matchmaking flow, parties enter from the Party service. The initialize method is called every time a new party enters the Matchmaking service via MatchmakingService.enterMatchmaking, which is called as part of PartyService.enterMatchmaking.

interface MatchmakingPlugin {
  fun initialize(
    queueKey: MatchmakingQueueKey,
    party: Matchmaking.Party
  ) :NewGameInstance? {
      // Custom logic to run before adding this potential match to a queue

Add custom logic to the initialize method to determine one of the following outcomes:

  • Party is added to the matchmaking queue
  • Party is fast-tracked to the game instance
  • Party is prevented from joining the queue

If a party is successfully added to the matchmaking queue, the initialize method returns null and a Matchable is created for that party. This Matchable is like a train car, where there’s space for other parties to join until the car is full.

If a party contains all the players needed for a match, and the developer wants to enable fast-tracking the match and ignore any mismatches that would typically invalidate a matchup (such as skill disparity), initialize can generate a NewGameInstance. For example, custom games for events like in-house tournaments may want to skip matchmaking and place players directly in a match regardless of skill level or other standard matchmaking data.

If the party cannot join the matchmaking queue due to validation errors, an ExtException is thrown. The party leader will receive the PartyService_FailedToEnterMatchmaking error.

Matching parties #

The primary method in the Matchmaking Plugin is matchParties, which is used to perform matchmaking operations such as comparing players and moving them between Matchables.

Compare matches #

As part of the matchParties method, Matchables are compared using a set of developer-defined matchmaking data, such as skill level or preferred game server zones. Only two Matchables can be compared at once. One is considered the anchor Matchable, and the other is considered the other Matchable.

interface MatchmakingPlugin {
   fun matchParties(
      queueKey: MatchmakingQueueKey, 
      anchor: Matchable, 
      other: Matchable
   ): NewGameInstance? {
        // Custom matchmaking logic

Within each queue, the oldest Matchable is selected as the anchor. All other Matchables in that queue are classified as other, and each of these are compared to the anchor to check viability of combining parties into one Matchable. The anchor Matchable begins comparison with the next oldest Matchable, and continues through all Matchables in the queue until it reaches the accepted state for a full Matchable and a NewGameInstance is returned.

Match Parties Logic

Add custom logic to the matchParties method to determine one of the following outcomes:

  • a NewGameInstance is generated and details are sent to the game server
  • matchParties is called again with a new other Matchable
  • endOfLoop is called and a new Matchable becomes the anchor

By default, if the end of the loop is reached and no NewGameInstance has been generated, the anchor position is moved to the next oldest Matchable in the queue. To add custom behavior at this stage, implement endOfLoop as described in Add custom behavior after complete loop.

If the matchParties method throws an exception, the Matchmaking service logs an error and removes both the anchor Matchable and the other Matchable from the queue to allow for debugging. Players are notified via a SessionChangedV1Notification. The anchor position is then reset to the oldest Matchable in the queue.

For each comparison, the following information is available to the Matchmaking Plugin for consideration in your matchmaking logic. This data is stored on the Matchable object.

Match Comparison Data
  • parties - list of matchmaking parties
    • partyId: UUID
    • ext: ExtMatchmakingParty
    • preferredGameServerZones: List
    • players: List<Matchmaking.Player> - details for all players within that matchmaking party
    • playerCount: Int - count of players in this party
    • secondsInQueue(): Int
  • players - list of all players in match parties
    • playerId: UUID
    • socialId: UUID
    • displayName: PragmaDisplayName
    • teamNumber: Int
    • partyId: UUID
    • gameServerZoneToPing: Map<String, Int>
  • matchmakingKey: ExtMatchmakingKey - the ext data associated with the queue
  • gameServerVersion: String - the version of the game server the match would be played on

Move parties between Matchables #

When the matchmaking logic that compares Matchables determines that parties should be moved from one Matchable to another, they can be moved by invoking the takePartiesFrom method.

interface Matchable {
    matchable: Matchable, 
    parties: List<Matchmaking.Party>
You cannot take parties from an Active Match.
Moving parties between Matchables does not automatically update team number. Use the functions in the Teams section to change team numbers as necessary.

Add custom behavior after matchmaking loop #

If an anchor Matchable makes it through the entire queue without forming a complete match, the default behavior is that the anchor position is moved to the next oldest Matchable in the queue. Custom behavior can be added before the anchor position is moved by defining logic using the Matchmaking Plugin endOfLoop method:

fun endOfLoop {
    queueKey: MatchmakingQueueKey,
    anchor: Matchable
): NewGameInstance?

Example: Use this function to examine data like match queue time and create a NewGameInstance immediately even if the matchmaking process failed to build an ideal complete Matchable. This can be leveraged to build matches with a limited matchmaking pool, such as during testing.

Starting a new game instance #

When a NewGameInstance is created all the data needed for a game instance to start on a game server is sent to the Match Lifecycle service. The Matchable that triggered the new game instance is then removed from the matchmaking queue.

Adding parties to game instances #

The Active Matches feature allows game instances that have already been sent to a game server to accept new players. New game instances that are configured to allow for continued matchmaking can use logic in the buildMatch method to find additional parties.

Example: A battle royale mode may keep all players in a pre-game lobby where they can interact with each other before the full game has been built. This lobby exists on a game server, and this match requires the use of a Matchmaking game instance.

To use the Active Match feature, the buildMatch function for Active Matches must be implemented in addition to the matchParties method.

interface MatchmakingPlugin {
    fun buildMatch(
      queueKey: MatchmakingQueueKey,
      activeMatch: ActiveMatch,
      matchable: Matchable
    ) {
        // Custom matchmaking logic for active matches

To add new players to an Active Match, information is sent via WebSocket connection using the MatchMorePlayersFoundV1Notification. If you want to use this feature, you must be using WebSockets instead of HTTP.

Active Matches contain a list of removedPlayers that represents all players that were previously removed from the game instance. This can be used during the buildMatch step to prevent players from being placed in a game instance they’ve already left.

The Active Match’s players and removedPlayers lists are updated when players join or are removed from the game instance on the game server. This allows the Matchmaking Plugin to rely on information being up-to-date within a few seconds.

To remove an Active Match from matchmaking once the match has enough players, use activeMatch.stopMatchmaking(). Game servers can also directly request to leave matchmaking by invoking the endpoint MatchLifecycleRpc.LeaveMatchmaking. The Match Lifecycle service automatically removes the match from matchmaking if the game instance ends due to invoking MatchLifecycleRpc.MatchEnd, the game server timing out with the KeepAliveV1, or if the MatchAbsoluteTimeout is reached.

The game server receives updates on its matchmaking status, and the following SDK-level events exist to monitor changes.


Matchmaking Service Calls #

The table below contains a full list of all the Matchmaking service calls. Optionally, use the calls in the verification call column to perform additional verification for the respective calls.

Callsectionverification call

Example workflow #

In this example, we have a queue of Matchable objects (represented by rectangles) waiting to be matched with other Matchable objects so a NewGameInstance can be generated. Each Matchable object contains one or more parties (represented by a rounded square). Each party contains one or more players (represented by a circle). In our example, we’re basing our matchmaking logic on a player’s MMR (represented by the number in the player’s circle).

Matchmaking Logic Example

Additional examples #

Example: Party enters matchmaking service #

When a party enters the matchmaking service it joins the matchmaking queue as a Matchable object. The matchmaking service uses logic defined in the Matchmaking Plugin’s matchParties method to compare Matchable objects. During this matchmaking process, parties may be added to or removed from Matchable objects. If the matchParties method determines that two Matchables are a match, a NewGameInstance is generated and the Matchable is sent to the game server.

Example: Game Instance reenters matchmaking #

Depending on your settings, an Active Match can reenter the matchmaking service and accept additional parties. The buildMatch method is called when an Active Match reenters the matchmaking process. Like the matchParties function compares a queued Matchable to an anchor Matchable, the buildMatch function compares queued Matchable with the Active Match.