Matchmaking in PlayFab

In this post, I will go through the matchmaking process of PlayFab.

What is Matchmaking?

Matchmaking allows players or groups of players to find each other and start a multiplayer game by connecting to a common server. You can find an excellent description in the PlayFab documentation. I will show you the end-to-end process.

Matchmaking Process in PlayFab

In my earlier post, I explained how to build an online multiplayer game using Unity and PlayFab. Check that post first, if you need more information about using the PlayFab API and Mirror Networking. Here we extend that solution with matchmaking.

The following diagram shows the matchmaking steps:

Matchmaking in PlayFab

(1) Player Authentication

Before starting the matchmaking process, the player is required to first log in. You check this earlier post, which describes how to implement user authentication.

(2) Start Multiplayer Game

Our player clicks on “Start multiplayer game”, intending to find someone to play with. To start the matchmaking process, we need to create a ticket. You should provide the following information:

  • Entity key of the user: if the authentication was successful, the LoginResult object will contain an EntityId, which identifies the player account.
  • User attributes: you can specify matchmaking rules, and these attributes will be used to decide if there should be a valid match between the tickets. If you choose automatic server allocation for a queue (start a game server after the matchmaking process was successful), set the region selection rule and add the latency attribute to the ticket.
  • Name of the queue which will hold the tickets waiting for a match.
void CreateMatchMakingTicket(string entityId) { PlayFabMultiplayerAPI.CreateMatchmakingTicket( new CreateMatchmakingTicketRequest { Creator = new MatchmakingPlayer { Entity = new PlayFab.MultiplayerModels.EntityKey { Id = entityId, Type = "title_player_account", }, Attributes = new MatchmakingPlayerAttributes { DataObject = new { latencies = new object[] { new { region = "NorthEurope", latency = 100 }, new { region = "WestUs", latency = 150 } } }, }, }, GiveUpAfterSeconds = 120, QueueName = "TestQueue", }, this.OnMatchmakingTicketCreated, this.OnMatchmakingError); }
Code language: JavaScript (javascript)

(3) Submitting a Ticket

Before submitting your first ticket, make sure you have created a queue in PlayFab. Go to Multiplayer > Matchmaking (Preview) > New queue. Then configure the queue. The options are straightforward.

For allocating a server after a successful match select “Enable server allocation” and set the “Build” you will use for your game servers. Also set the region selection rule, which is mandatory in case of automatic server allocation.

If the queue and the ticket you have is correct, the CreateMatchmakingTicket method will submit it to the requested queue.
The player sees on the screen “Waiting for other players to join…”.

(4) Polling Matchmaking Status

PlayFab supports only the polling method, so clients need to ask PlayFab frequently if a match has already been found. PlayFab limits the number of requests, but you may poll every 6 seconds.

private void OnMatchmakingTicketCreated(CreateMatchmakingTicketResult obj) { ticketId = obj.TicketId; coroutine = PollMatch(6.0f); StartCoroutine(coroutine); } private IEnumerator PollMatch(float waitTime) { while (true) { GetMatchingTicket(); yield return new WaitForSeconds(waitTime); } } private void GetMatchingTicket() { PlayFabMultiplayerAPI.GetMatchmakingTicket( new GetMatchmakingTicketRequest { TicketId = ticketId, QueueName = "TestQueue", }, this.OnGetMatchmakingTicket, this.OnMatchmakingError); }
Code language: JavaScript (javascript)

(5) Creating a Match

PlayFab check if the attributes fit the pre-defined rules, and it creates a match by bringing tickets together.

(6) Allocating a Game Server

PlayFab allocates a game server using the earlier defined “Build”. After PlayFab creates the match, the callback to the clients will contain the game server’s address, port, and information about other players.

(7) Clients Connect to the Server

The clients can then connect to the game server and start the game.

private void OnGetMatchmakingTicket(GetMatchmakingTicketResult obj) { Debug.Log("GetMatchmakingTicket: " + obj.Status); if (obj.Status.Equals("Matched")) { StopCoroutine(coroutine); matchId = obj.MatchId; GetMatch(); } } private void GetMatch() { PlayFabMultiplayerAPI.GetMatch( new GetMatchRequest { MatchId = matchId, QueueName = "mygamematchmakingqueue", }, this.OnGetMatch, this.OnMatchmakingError); } private void OnGetMatch(GetMatchResult obj) { // Only if server allocation is enabled // serverIP = obj.ServerDetails.IPV4Address; // serverPort = obj.ServerDetails.Ports[0].Num; }
Code language: JavaScript (javascript)

Conclusion

As you can also see, the basic process is straightforward and easy to implement. You can extend this by adding new rules or matching group of players. Unfortunately, the matchmaking feature is currently available only in “Preview” mode, but through my experience, I can testify that it works reliably.

3 thoughts on “Matchmaking in PlayFab”

  1. Hello! Nice article,a lof of helpful.
    I have question. I create ticket for two different players and my ticket status show me WatingForMatch and after 120 second I get status canceled because is timer over. My question, who is must check players attributes?
    I need to create lobby and server or what I need to do?
    Thank you advance!

    1. Hi Ivan,

      PlayFab itself checks the attributes and matches the tickets. You just need at least two players with matching attributes according to a matching rule. Both players should create and submit a matchmaking ticket to PlayFab.

      I added some more code that helps maybe further.

      After PlayFab finds two matching tickets, it will give you and your partner back a MatchId. Both of you are then “matched”.

      You can then stop the polling, and invoke the GetMatch method, which will come back with the server and port number (if you have enabled the server allocation option to use PlayFab servers for the game sessions).

      Your partner will get the same IP and port, and so both of you can join to the same game server.

      1. It’s just that I’m creating a matchmaking ticket for two players, and I’m not creating it from Unity, but from my Web API. And when I call GetMatchmakingTicket I get the status WaitingForMatch every time. What could this be related to?

        look this my code from my Web API
        Create Ticket
        public async Task CreateMatchMaking(string EntityToken, string entityId, string entityType)
        {

        string url = “https://E64AC.playfabapi.com/Match/CreateMatchmakingTicket”;
        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url);

        string json = CreateObject(entityId, entityType);

        request.Content = new StringContent(json, Encoding.UTF8, “application/json”);
        HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(“application/json”));
        client.DefaultRequestHeaders.Add(“X-EntityToken”, EntityToken);

        var response = await client.SendAsync(request);
        string json2 = await response.Content.ReadAsStringAsync();
        string ticket = JsonConvert.DeserializeObject(json2).data.TicketId;
        return ticket;
        }

        And This Check status Method

        public async Task CheckStatus(string ticketId,string entityToken)
        {
        string url = “https://E64AC.playfabapi.com/Match/GetMatchmakingTicket”;
        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url);
        string json = RequestGetMatchmakingstatus(ticketId);

        request.Content = new StringContent(json, Encoding.UTF8, “application/json”);
        HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(“application/json”));
        client.DefaultRequestHeaders.Add(“X-EntityToken”, entityToken);

        var response = await client.SendAsync(request);
        return await response.Content.ReadAsStringAsync();
        }

Leave a Comment

Your email address will not be published. Required fields are marked *