👥Matchmaking

Integrating Matchmaking with PlayFlow

PlayFlow's matchmaking system is designed to streamline the process of bringing players together in a game. When a player opts for matchmaking, they're placed into a matchmaking pool. This pool is where the magic happens — it's an aggregation point for all players looking to join a game.

How Matchmaking Works

Matchmaking Pool: As players initiate matchmaking, they are added to a matchmaking pool. This pool serves as a temporary holding area where players await pairing based on the matchmaking criteria.

Criteria-Based Matching: Players can be matched based on specific criteria, such as skill level (Elo), regions, game type preferences, or custom parameters. If no criteria are defined, the system will default to matching players without discrimination, ensuring that everyone gets into a game as swiftly as possible.

Server Launching: Once suitable matches are made, PlayFlow takes care of the rest by automatically launching a dedicated server for the matched players. This seamless process ensures that players can jump straight into the action without worrying about server setup or availability.

Dynamic Matchmaking Engine: At the heart of PlayFlow's matchmaking system is a dynamic engine designed to ensure players are matched together efficiently. This engine constantly adjusts to the pool of waiting players and their respective criteria, aiming to minimize wait times while optimizing match relevance.

This dynamic approach to matchmaking means that the system is continually working to find the best possible matches for players at any given moment, adapting to the ever-changing pool of participants. The result is a more enjoyable gaming experience, where players spend less time waiting and more time playing.


Matchmaking Quick Start Guide

1. Triggering Matchmaking

To initiate matchmaking, you can set up an input trigger or a button in the UI. In this example, pressing the K key begins the matchmaking process:

if (Input.GetKeyDown(KeyCode.K))
{
    Debug.Log("Starting Find Match");
    ...
}

2. Setting Up Player Data

Create a new instance of PlayFlowManager.PlayerData to hold the player's information:

PlayFlowManager.PlayerData playerData = new PlayFlowManager.PlayerData();

3. Assigning a Unique Identifier

Assign a unique identifier to each player. This example uses the device's unique identifier:

playerData.player_id = SystemInfo.deviceUniqueIdentifier;

4. Specifying Region Preferences

Define the player's preferred regions for matchmaking to ensure lower latency:

playerData.region = new List<string> {"us-east", "us-west"};

5. (Optional) Using Elo for Matchmaking

If you're implementing skill-based matchmaking, specify the player's Elo:

playerData.elo = 1500;

6. Setting the Game Type

Indicate the game type the player wishes to engage in. This helps in matching players interested in the same game mode:

playerData.game_type = "soccerMap";

7. Adding Custom Parameters (Optional)

For more refined matchmaking, you can include custom parameters:

playerData.custom_parameters = new List<PlayFlowManager.CustomParameter>();
PlayFlowManager.CustomParameter customParameter = new PlayFlowManager.CustomParameter();
customParameter.key = "playerDifficulty";
customParameter.value = "medium";
playerData.custom_parameters.Add(customParameter);

8. Initiating Matchmaking

Call PlayFlowManager.FindMatch with the necessary parameters, including the clientToken, playerData, and a callback method OnMatchFound to handle the match found event:

StartCoroutine(PlayFlowManager.FindMatch(clientToken, playerData, OnMatchFound));

Full Example:

void Update() 
{
    // Check if the 'K' key is pressed to initiate matchmaking
    if (Input.GetKeyDown(KeyCode.K))
    {
        Debug.Log("Starting Find Match");

        // Create a new PlayerData object to store player's matchmaking info
        PlayFlowManager.PlayerData playerData = new PlayFlowManager.PlayerData();

        // Assign a unique identifier for the player using the device's unique identifier
        playerData.player_id = SystemInfo.deviceUniqueIdentifier;

        // Set the player's preferred matchmaking regions
        playerData.region = new List<string> {"us-east", "us-west"};

        // (Optional) Set the player's Elo for skill-based matchmaking
        playerData.elo = 1500;

        // Specify the game type the player wishes to play
        playerData.game_type = "soccerMap";

        // Initialize the list for custom parameters
        playerData.custom_parameters = new List<PlayFlowManager.CustomParameter>();

        // Create and add a custom parameter for additional matchmaking criteria
        PlayFlowManager.CustomParameter customParameter = new PlayFlowManager.CustomParameter();
        customParameter.key = "playerDifficulty";
        customParameter.value = "medium";
        playerData.custom_parameters.Add(customParameter);

        // Call FindMatch coroutine with the player data and a callback for when a match is found
        StartCoroutine(PlayFlowManager.FindMatch(clientToken, playerData, OnMatchFound));
    }
}

This method encapsulates the entire process from initiating matchmaking with a key press to handling the outcome when a match is found.

Handling the Match Found Event in PlayFlow

Once a match is found, the OnMatchFound method is crucial for managing the transition of the player into the matched game session. This method should not only acknowledge the match but also initiate the connection process to the designated game server.

OnMatchFound Method

private void OnMatchFound(Server server)
{
    Debug.Log($"Match Found with Server: {server}");
    
    // Iterate through the server's ports and log them
    foreach (var port in server.ports)
    {
        Debug.Log($"Port: {port.Key} = {port.Value}");
    }

    // Attempt to start a connection if the standard HTTPS port 443 is available
    if (server.ports.TryGetValue("443", out int port443))
    {
        StartConnection(server.server_url, (ushort)port443);
    }
    else
    {
        Debug.LogError("Port 443 not found in server ports");
    }
}

This method logs the matched server details and checks for the availability of port 443, typically used for secure connections. If available, it proceeds to initiate a connection.

StartConnection Method

private void StartConnection(string url, ushort port)
{
    // Attempt to connect three times with a 2-second delay between each attempt
    for (int i = 0; i < 3; i++)
    {
        StartCoroutine(StartConnectionCoroutine(url, port));
    }
}

This method attempts to establish a connection to the game server by calling a coroutine, StartConnectionCoroutine, up to three times to ensure a robust connection attempt.

StartConnectionCoroutine Method

private IEnumerator StartConnectionCoroutine(string url, ushort port)
{
    // Wait for 3 seconds before attempting the connection
    yield return new WaitForSeconds(2);
    
    Debug.Log($"Starting Connection to: {url} : {port}");
    
    // Get the transport component from the NetworkManager
    Bayou transport = NetworkManagerObject.GetComponent<Bayou>();

    // Set up the transport for a secure connection and initiate it
    transport.SetUseWSS(true); // Enable WebSocket Secure (WSS)
    transport.SetPort(port);
    transport.SetClientAddress(url);
    transport.StartConnection(false);
}

The coroutine waits for 2 seconds before logging the connection attempt and starting the connection. It configures the Bayou WebSockets transport (FishNet) component for a WebSocket Secure (WSS) connection using the given URL and port, and then attempts to start the connection.


Incorporating these methods into your PlayFlow integration ensures a smooth transition from matchmaking to game session connection, enhancing the overall player experience.

Last updated