Open Match: Writing a Skill Based Match Function

Jon Foust
4 min readOct 6, 2020

If you’re still following along, we’ve explored Open Match services and how they help build your game’s matchmaker. Skill based matchmaking is very common for online multiplayer games, so let’s explore how to write a skill based match function. We’ll go over a few setup steps and considerations to ensure you’re providing the Match Function all the data to connect players. Full disclosure: This blog post will provide dummy data (I’ll explain where it’s used and why) to represent your player information throughout the matchmaking process. Your game may have player data stored externally from Open Match.

Profiles and Ticket Pools

In my previous blog post, I discussed what Profiles and Ticket Pools are. Profiles set the criteria, such as a game mode, for our matches. Open Match uses one to three types of filters to create the criteria for profiles to populate ticket pools. To specify skill ranges, DoubleArgFilters are used to set min and max values for a given DoubleArg. If a ticket fits the criteria, it’ll enter a collection of tickets that have also met the match criteria called a ticket pool. Our Match Function will look through ticket pools to select tickets for matches. Here’s a snippet using a max and min DoubleArg value to define a skill range for a profile:

The snippet above is creating overlapping profiles based on skill. Overlapping profiles occur when profiles intersect based on filters (such as skill). Tickets that end up in multiple ticket pools are considered for numerous matches and will likely find a match faster. To achieve overlapping profiles, make min/max DoubleArgFilters intersect with one another. Here’s an example (from Open Match Documentation):

  • Profile1 has a Pool that filters all Tickets with skill levels 0 to 5.
  • Profile2 has a Pool that filters all Tickets with skill levels 2 to 8.
  • Profile3 has a Pool that filters all Tickets with skill levels 6 to 10.
Profiles will generate ticket pools based on filters. Tickets may end up in multiple ticket pools.

Overlapping profiles are great but will cause collisions when tickets are selected for multiple matches. We’ll explore how to decouple these collisions later on. Now that we’ve set up our ticket pools, we should finally get into writing our Match Function.

Match Function

Now that we’ve configured our profiles to filter tickets according to skill ranges, we can pass the profiles and ticket pools to the Match Function to select a group of tickets to generate a Match Proposals. Match Proposals hold all information which will be used to generate a match such as the tickets, game mode, match profile, etc.

The following Match Function uses skill to group players together. It accomplishes the following:

  • Checks if the current ticket pool has enough tickets to satisfy a match proposal
  • Sorts tickets so consecutive tickets are closer in skill
  • Removes tickets from pool
  • Returns Match Proposals to be streamed to Open Match

This is a great first step for your Match Function. If this is the behavior you want, congratulations, you’ve written your first Match Function! This match function works best with Match Profiles that aren’t overlapping. Our profiles overlap, so let’s settle any colliding proposals.

Open Match provides an Evaluator that is responsible for removing collisions and streaming proposals back to Open Match. To add this to your match function, you can add an extension which adds Evaluation criteria for the default Evaluator.

The following snippet is the complete match function with evaluation criteria. It adds the following functionality:

  • Generates a score which represents the quality of the match
  • Appends the quality score to the match proposal

The Default Evaluator will look at match proposals and any criteria to choose the best matches first. It will choose matches with better quality first to ensure a balanced, enjoyable experience. Once you’ve finished implementing your matchmaking logic, you will deploy your Match Function service on a Kubernetes offering of your choice (such as GKE).

The Matchmaking Request

With your matchmaker up and running, you might be wondering what submitting a request will look like. A ticket represents a player or group’s matchmaking request. Tickets allow you to add attributes to your ticket which represent player data, including:

  • Skill
  • Role
  • Game mode
  • Region
  • Ping

Here’s what a ticket could look like for your skill-based Match Function:

Open Match tickets accept numerical search fields as DoubleArgs. You can provide a key-value to represent this field. Here we specify the string skill as our key and a randomly generated float as our value. We are randomly generating a float here to simulate a skill rating accessed from externally stored player data. To stay true to typical skill level distribution, I thought it would be best to normalize skill levels within a given range. To do so, I’ve added a method to randomly generated a number within the range 0–5 with a normal distribution of 3 called generateSkill.

Wrapping up

Skilled based matchmaking is a challenging feature to implement because matchmaking logic is very game specific. I hope you’ve gained a bit of insight into writing match logic and you’re inspired to explore Open Match further and make your matchmaker your own. As always, thanks for tuning in and I’m here to answer any questions so reach out to me on twitter.

--

--

Jon Foust

Developer Advocate @ Google. Gamer. Maker. Trying to make things easier for others by doing the hard stuff myself. Opinions are my own.