Getting Started

Get started with Matchmaking quickly and explore example scenarios for various genres.

Matchmaking in session-based games generally aims to:

  • find other players based on criteria like region, latency, skill, or game parameters;

  • search for servers to join based on available capacity [or ping, region, skill, map, mode];

  • start new server if existing servers are full or don't satisfy player criteria.

Player experience comes first, defining our core objectives:

  • high match fill rate and social feature integration (play with friends in groups),

  • fast matches with controlled match quality (low latency, shared preferences),

  • reliable and predictable matchmaking process with global availability.

Follow along this video to get started with our Matchmaker service:

✔️ Preparation

Testing our Matchmaker is entirely free, no credit card required.

Free Tier allows up to 3 hours of runtime on our shared test cluster, after each restart.

This tutorial assumes you have already:

Matchmaking Architecture

This guide will focus on Matchmaking API and Backfill API.

There are four (4) important flows of data when matchmaking is involved:

  1. Matchmaking API is used by Game Clients to communicate with Matchmaker:

    1. for group management, server assignment, and monitoring,

    2. for ping measurement with Ping Beacons.

  2. Deployments API is used to deploy, scale, and manage your Dedicated Servers by Matchmaker.

  3. Netcode Transports are used to communicate between Game Clients and Dedicated Servers:

  4. Backfill Match to replace or add more players from Server.

After release, your matchmaker will need to run 24/7 to ensure players across the world can join servers.

🍀 Simple Example

Start with a simple example and test the basic matchmaking player flow:

1. Set Up on Free Tier

☑️ Register for your free Edgegap account and open the Matchmaker dashboard page.

☑️ Click on Create Matchmaker first, then input:

  • matchmaker name - for your own reference, e.g. quickstart-dev ,

  • upload our Simple Example JSON configuration.

🍀 Simple Example (Minimal Recommended Configuration):

{
  "version": "3.2.0",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "simple-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "",
        "version": ""
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 1,
              "min_team_size": 2,
              "max_team_size": 2
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 100,
              "max_latency": 200
            }
          }
        },
        "expansions": {}
      }
    }
  }
}

Troubleshooting and FAQ:

The application configuration is not valid for profile XYZ.
Docker image for '2024.01.30-16.23.00-UTC' is not cached.

🌟 Upgrade to Pay as You Go tier to unlock instant deployments with Caching.

  • You may proceed anyway, though we recommend testing your deployment time.

☑️ If no validation errors appear, hit Create and Start and wait for the process to complete. This will result in a new free cluster starting, with your Simple Example matchmaker.

✅ You may now proceed to the next step.

2. Explore Configuration

As we release updates to Matchmaker, each new version uses Semantic Versioning to clearly communicate the impact of changes by interpreting format major.minor.patch:

  • 🔥 major versions include breaking changes and require integration review,

  • 🌟 minor versions include substantial backwards-compatible improvements,

  • 🩹 patch versions include bug fixes and minor improvements.

Use Matchmaker In-Depth to better understand and debug possible matchmaking flows while in development. We recommend disabling inspect API for your live matchmaker.

Some deployments may result in Errors. We attempt to resolve this by retrying deployment up to max_deployment_retry_count times automatically (without client confirmation).

To ensure that unexpected client crashes or abandoned tickets do not linger and take up your matchmaker resources, tickets will be cancelled after ticket_expiration_period causing their status to change to CANCELLED and then permanently deleted after ticket_removal_period .

The core of our matchmaking logic is configured in Profiles (Queues). Each profile is a completely isolated matchmaking queue, pointing to 🏷️ App Versions with pre-defined amount of required CPU and memory (RAM) resources.

Rules in the initial rule set must be met for players to be grouped together, each defined by three properties:

  • name of your choosing, e.g. - match size,

  • rule type, also known as operator, e.g. - player_count,

  • and lastly operator attributes, e.g. team_count or max_team_size.

Player Count Rule

This is a special rule defining how many players need to match to initiate assignment:

  • team_count refers to number of teams, 1 team may be used for cooperative or free-for-all modes,

  • min_team_size refers to the minimum number of players per team.

  • max_team_size refers to the maximum number of players per team.

Our simple example demonstrates a cooperative game with 2 players.

Latencies Rule

latencies is a special rule optimizing the ping of player matches:

  • reduce client-server latency by removing regions with high latency (above threshold),

  • improve match fairness by grouping players with similar latency (below difference).

Rule Example: beacons

beacons rule configured with "difference": 100, "max_latency": 200 will match:

Alice and Bob may match:

  • Tokyo is discarded (>200 ms),

  • latency for Chicago within 100 ms absolute difference.

Beacon City
Match
abs(A - B) [ms]
Alice [ms]
Bob [ms]

Chicago

75.0

12.3

87.3

Los Angeles

145.6

32.4

Tokyo

n/a

n/a

Alice and Charlie will never match:

  • no beacons have < 200 ms latency for both players,

  • Alice lives in North America - Illinois,

  • Charlie lives in Asia - Japan.

Beacon City
Match
abs(A - B) [ms]
Alice [ms]
Charlie [ms]

Chicago

n/a

n/a

12.3

Los Angeles

n/a

n/a

145.6

Tokyo

n/a

n/a

24.2

✅ You may now proceed to the next step.

3. Review Instance Details

☑️ Review details of your new matchmaker in our dashboard once it’s initialized:

  • Status indicates service health, may be ONLINE, OFFLINE, or ERROR.

  • Identifier helps Edgegap staff find your matchmaker quickly if you need help troubleshooting.

  • Started at can be useful to track down the latest update time.

  • Size corresponds to one of our Pricing Tiers.

  • API URL will be used by Game Clients and Game Servers to communicate with your matchmaker.

  • Swagger URL is a handy openAPI specification GUI we provide to explore API schema.

  • Auth Token is a unique secret token used by Game Clients and Game Server for authentication.

To test your new matchmaker, you will need the Swagger URL, API URL and Auth Token.

✅ You may now proceed to the next step.

To update your matchmaker rules in development, edit your configuration and restart it.

4. Test Tickets API

Please wait for up to 5 minutes after starting your matchmaker to allow DNS propagation to complete.

☑️ First, open your Swagger URL to inspect your openAPI schema in the swagger GUI:

☑️ Click on Authorize 🔒, paste your Auth Token, and confirm by clicking on Authorize.

☑️ Scroll down to Ticket API - POST /tickets, expand and click Try it out.

☑️ Preview your request:

  • notice player_ip set to null - this will cause Matchmaker to use the IP address automatically added to your request (see Matchmaker In-Depth for alternatives),

  • profile refers to your Profiles (Queues),

  • attributes include values for your matchmaker rules, in this case for the latencies rule,

    • rule player_count is the only rule which doesn’t require any attributes in player tickets.

☑️ Click Execute and review the response to your player ticket request:

☑️ Create a second ticket by hitting Execute again, so our two players match and a server is started.

☑️ Collapse POST /tickets and open GET /tickets/{ticketId}, then click Try it out.

☑️ Input ticket ID from the response in previous step and click Execute.

☑️ Review the updated assignment for your player ticket:

  • status changed to MATCH_FOUND first, while keeping assignment set to null to indicate players have matched and a server is being assigned,

☑️ Click Execute again to check on your ticket, and review the updated assignment for your ticket:

  • status changed to HOST_ASSIGNED with assignment containing details of the assigned server.

Troubleshooting & FAQ

My ticket is stuck in SEARCHING .

  • Please verify that you’ve created enough tickets with overlapping criteria adhering to your configuration.


My ticket is stuck switching between MATCH_FOUND and TEAM_FOUND repeatedly.

  • Free Tier accounts are limited to 1 deployment at a time. Please consider upgrading or stop your current deployment to start a new one.


My ticket goes straight to CANCELLED.

  • Your ticket reached it’s expiration. Recreate a new ticket or increase the expiration period in your configuration for testing purposes.


I receive HTTP 404 Not Found when checking on my ticket.

  • Your ticket was removed either by a DELETE request, or by reaching it’s removal period (starts after ticket is expired, defined in your configuration). Recreate a new ticket or increase the expiration/removal periods in your configuration for testing purposes.

☑️ Inspect your new deployment in our dashboard:

  • notice each deployment is tagged with all ticket IDs and profile for added traceability.

A few seconds after finding a match, memberships proceed to status:HOST_ASSIGNED indicating that your deployment is now ready and your game server is initializing.

Each player reads their ticket_id and assignment and attempt connection using the (deployment URL) and the External Port. Your game server may be still initializing at this time, so players must retry connection several times, until exceeding your usual server initialization time:

To connect from PIE (Editor) during development and testing, press the tilde key ~ and type open {URL}:{port} and wait for your editor to load the map.

To connect from a game client build (and in live production environment) try

We do not ask players to confirm the match, as we aim to provide shortest possible time to gameplay, high match fill rate, and minimize queue dodging and match cancellations.

Players should save their assignment ID persistently between game restarts, so that in case of game client crash they can retrieve the connection details and attempt reconnecting.

☑️ Try connecting from your game client to the assigned server.

☑️ Once you verify you’re able to connect to your Deployment without issues and are done testing, Stop your Deployment to free up capacity in your account for the next build.

✅ You may now proceed to the next step.

Find the openAPI specification for testing at {matchmaker-url}/swagger/v1/swagger.json.

5. Game Integration

Matchmaker integrates with:

☑️ In Game Client, we recommend providing ticket status updates to players using in-game UI for best player experience. See:

☑️ In Game Client, ensure you’re handling non-retryable errors:

  • HTTP 404 Not Found - ticket has been deleted,

  • HTTP 500 Internal Server Error - temporary service outage.

☑️ In Game Server, read player preferences and initial server context:

  1. Injected Variables (Matchmaker) to retrieve initial players’ matchmaking data.

  2. Injected Variables (App Versions) for version parameters, settings, and secrets.

  3. Injected Variables (Deployment) for deployment information, IP, location, etc...

☑️ Once players connect, Game Server and Game Clients start a loading scene - 3D scene, a lobby-like social UI, or a loading screen with a progress bar, to indicate initialization is progressing.

☑️ Ensure your deployment will be stopped properly once the match concluded.

🙌 Congratulations, you’ve completed Matchmaking integration! To learn more, keep reading.

🏁 Advanced Example

A full fledged configuration utilizing all matchmaking features including Profiles (Queues), Rules, and Rule Expansion may look like this:

🏁 Advanced Example (Complete Example Configuration)
{
  "version": "3.2.0",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "allowed_cors_origins": [
    "https://*.my-game-server.com"
  ],
  "profiles": {
    "advanced-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m"
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 1,
              "min_team_size": 4,
              "max_team_size": 4
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 125
            }
          },
          "elo_rating": {
            "type": "number_difference",
            "attributes": {
              "max_difference": 50
            }
          },
          "selected_game_mode": {
            "type": "string_equality"
          },
          "selected_map": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "30": {
            "elo_rating": {
              "max_difference": 150
            },
            "beacons": {
              "difference": 125,
              "max_latency": 250
            }
          },
          "60": {
            "elo_rating": {
              "max_difference": 200
            }
          },
          "180": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 1,
              "max_team_size": 4
            },
            "beacons": {
              "difference": 99999,
              "max_latency": 99999
            }
          }
        }
      }
    }
  }
}

🎾 Custom Lobby

Custom lobbies (private lobbies, sandbox levels) are a very popular option for couch multiplayer and testing new features in games before they enter main game modes. Typically require the least amount of restrictions, but aim to ensure that players can Group Up.

🎾 Custom Lobby Example
{
  "version": "3.2.0",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "custom-lobby-example": {
      "ticket_expiration_period": "3m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m"
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 1,
              "min_team_size": 4,
              "max_team_size": 4
            }
          },
          "lobby_id": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "10": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 1,
              "max_team_size": 4
            }
          }
        }
      }
    }
  }
}

For private lobbies without public access, set "team_size": 1 and make the group owner start the game alone. Owner may share group and host assignment details to any number of members to join up.

🥛 Backfill Showcase

Building on 🍀 Simple Example, this configuration showcases Matchmaker In-Depth with Matchmaker In-Depth.

🥛 Backfill Configuration Example
{
  "version": "3.2.0",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "backfill-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 1,
              "min_team_size": 4,
              "max_team_size": 4
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 100,
              "max_latency": 200
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {}
      }
    }
  }
}

Optionally, some games may have special matchmaking needs, such as:

  • allow new players to join games in progress (friends or "randoms"),

  • replace players who abandon (leavers) after server starts to avoid restarting match,

  • allow spectators to join and observe tournament or friends’ matches (e-sports),

  • centralize players in larger servers to provide more social interactions (MMOs).

Backfill is a server-owned ticket representing players currently connected to the server. This ensures newly added players will respect your matchmaking rules when matched with current players.

Backfill Scenarios Visualized

The steps to complete a successful backfill are:

  1. Server creates Matchmaker In-Depth for each team separately, using values from:

    • Real assignment data retrieved from Injected Environment Variables (deployment).

    • Currently connected players' tickets:

      • from 📌 Injected Variables (matchmaker), previous backfills' assigned_ticket response, or mock data manipulated to match specific players,

      • replace backfill_group_size values with possible group sizes ,

  2. Game clients create new Matchmaker In-Depth with backfill_group_size array with values:

    • "1" if the player is matchmaking alone.

    • .

    • "new" if players enabled starting new games in addition to joining in-progress games.

  3. Game clients proceed to Find Match and pair players with the matching backfill.

  4. If the backfilled group didn't completely fill the team, the server may repeat this process with the newly backfilled players' tickets, to add more players and reach desired team sizes.

To create a Backfill-only profile, set min_team_size to 999,999 and disable ticket + ticket matches.

🥛 Backfill Example (Backfill Showcase)
{
  "profile": "backfill-example",
  "attributes": {
    "assignment": {
      "request_id": "cd28e6c66554",
      "fqdn": "cd28e6c66554.pr.edgegap.net",
      "public_ip": "192.168.2.14",
      "ports": {
        "game": {
          "internal": 7777,
          "external": 56890,
          "link": "cd28e6c66554.pr.edgegap.net:56890",
          "protocol": "UDP"
        },
        "web": {
          "internal": 22,
          "external": 57440,
          "link": "cd28e6c66554.pr.edgegap.net:57440",
          "protocol": "TCP"
        },
        "server": {
          "internal": 80,
          "external": 50110,
          "link": "cd28e6c66554.pr.edgegap.net:50110",
          "protocol": "TCP"
        }
      },
      "location": {
        "city": "Montreal",
        "country": "Canada",
        "continent": "North America",
        "administrative_division": "Quebec",
        "timezone": "America/Toronto"
      }
    }
  },
  "tickets": {
    "c3d057h5h6f7j889fk43": {
      "player_ip": "174.25.48.238",
      "attributes": {
        "beacons": {
          "New York": 12.2,
          "Los Angeles": 45.3,
          "Paris": 78.3
        },
        "backfill_group_size": [
          "2",
          "1"
        ]
      },
      "group_id": "192bb97e-7fd6-4d86-8ce4-61c53c9fef16",
      "id": "c3d057h5h6f7j889fk43",
      "created_at": "2024-08-20T13:38:05.251393+00:00"
    },
    "cqg0bg9583s738h9dkf6": {
      "player_ip": "217.34.85.142",
      "attributes": {
        "beacons": {
          "New York": 21.0,
          "Los Angeles": 30.2,
          "Paris": 101.1
        },
        "backfill_group_size": [
          "2",
          "1"
        ]
      },
      "group_id": "aea7df3c-d391-4ea3-a3ec-dded422fe7c8",
      "id": "cqg0bg9583s738h9dkf6",
      "created_at": "2024-08-20T13:38:05.251393+00:00"
    }
  },
  "assigned_ticket": null
}
🥛 Backfill Assignment Example (Backfill Showcase)
{
  "profile": "backfill-example",
  "attributes": {
    "assignment": {
      "request_id": "cd28e6c66554",
      "fqdn": "cd28e6c66554.pr.edgegap.net",
      "public_ip": "192.168.2.14",
      "ports": {
        "game": {
          "internal": 7777,
          "external": 56890,
          "link": "cd28e6c66554.pr.edgegap.net:56890",
          "protocol": "UDP"
        },
        "web": {
          "internal": 22,
          "external": 57440,
          "link": "cd28e6c66554.pr.edgegap.net:57440",
          "protocol": "TCP"
        },
        "server": {
          "internal": 80,
          "external": 50110,
          "link": "cd28e6c66554.pr.edgegap.net:50110",
          "protocol": "TCP"
        }
      },
      "location": {
        "city": "Montreal",
        "country": "Canada",
        "continent": "North America",
        "administrative_division": "Quebec",
        "timezone": "America/Toronto"
      }
    }
  },
  "tickets": {
    "c3d057h5h6f7j889fk43": {
      "player_ip": "174.25.48.238",
      "attributes": {
        "beacons": {
          "New York": 12.2,
          "Los Angeles": 45.3,
          "Paris": 78.3
        },
        "backfill_group_size": [
          "2",
          "1"
        ]
      },
      "group_id": "192bb97e-7fd6-4d86-8ce4-61c53c9fef16",
      "id": "c3d057h5h6f7j889fk43",
      "created_at": "2024-08-20T13:38:05.251393+00:00"
    },
    "cqg0bg9583s738h9dkf6": {
      "player_ip": "217.34.85.142",
      "attributes": {
        "beacons": {
          "New York": 21.0,
          "Los Angeles": 30.2,
          "Paris": 101.1
        },
        "backfill_group_size": [
          "2",
          "1"
        ]
      },
      "group_id": "aea7df3c-d391-4ea3-a3ec-dded422fe7c8",
      "id": "cqg0bg9583s738h9dkf6",
      "created_at": "2024-08-20T13:38:05.251393+00:00"
    }
  },
  "assigned_ticket": {
    "profile": "backfill-example",
    "player_ip": "244.13.201.244",
    "attributes": {
      "beacons": {
        "New York": 30.2,
        "Los Angeles": 10.5,
        "Paris": 123.9
      },
      "backfill_group_size": [
        "new",
        "1"
      ]
    },
    "id": "cqg0bg550h7uujd77khg",
    "group_id": "e0cf41c0-f88f-456e-a032-03b1d6821a9a",
    "created_at": "2024-08-20T13:38:08.251393+00:00",
    "status": "HOST_ASSIGNED"
  }
}

See Mirror Seat Management and FishNet Seat Management for player connection monitoring.

⚔️ Competitive Games

Competitive games focus on players competing against each other to achieve victory, whether as individuals (free for all) or teams. Ensure fair and balanced matches by pairing players or teams of similar skill levels, and maintain game pace by quickly finding fair competition.

⚔️ Competitive Game Example
{
  "version": "3.2.0",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "casual-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 2,
              "min_team_size": 5,
              "max_team_size": 5
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 150
            }
          },
          "selected_maps": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "30": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            }
          },
          "180": {
            "beacons": {
              "difference": 99999,
              "max_latency": 99999
            }
          }
        }
      }
    },
    "competitive-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m"
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 2,
              "min_team_size": 5,
              "max_team_size": 5
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 150
            }
          },
          "versus_ranks": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "120": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            }
          }
        }
      }
    },
    "challenger-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m"
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 2,
              "min_team_size": 5,
              "max_team_size": 5
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 150
            }
          },
          "elo_rating": {
            "type": "number_difference",
            "attributes": {
              "max_difference": 50
            }
          }
        },
        "expansions": {
          "120": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            }
          }
        }
      }
    }
  }
}

You may define multiple teams with 1 or more players each, for example:

Game Mode
Team Count
Team Size
Total Players

5v5 FPS

2

5

10

5v5 MOBA

2

5

10

20x3 Battle Royale

20

3

60

10p Free For All

1

10

10

Define multiple Profiles (Queues) for game mode specific rules and settings, and expand as needed.

  • For all matches:

    • restrict matchmaking latency to prevent matching players far away,

    • Group Up for pre-made parties and prevent exceeding team sizes,

    • slowly relax latency restrictions over time to find more players,

    • allocate more CPU or memory with different 🏷️ App Versions for specific profiles,

  • For casual matches:

    • omit rank restrictions to maximize match speed and match fill rate,

    • let players provide their map preferences to find a map suitable for everyone,

    • specify backfill group size to replace leavers without exceeding team sizes,

    • remove latency limitations to guarantee a match after 3 minutes (180s) of queue time.

  • For competitive matches:

    • restrict rank to only allow opponents with similar skill level,

    • use rank-up or rank-down ranks to match players at the league's rank extremes.

  • For the top 1% of high skill matches (challengers):

    • use numerical skill ratings (ELO) to gain fine control over skill distribution in matches,

    • wait longer before relaxing latency requirements due to lower amount of players.

🤝 Cooperative Games

Cooperative games require players to work together as a team towards a common goal, or AI opponent. Align players with similar preferences and gameplay habits. Replace players who leave, and improve 🟢 Connection Quality to provide a responsive player experience.

🤝 Cooperative Game Example
{
  "version": "3.2.0",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "cooperative-example": {
      "ticket_expiration_period": "3m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 1,
              "min_team_size": 4,
              "max_team_size": 4
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 150
            }
          },
          "selected_difficulty": {
            "type": "string_equality"
          },
          "selected_map": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "player_level": {
            "type": "number_difference",
            "attributes": {
              "max_difference": 10
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "moderation_flags": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "30": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            },
            "player_level": {
              "max_difference": 20
            }
          },
          "60": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 2,
              "max_team_size": 4
            }
          },
          "150": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 1,
              "max_team_size": 4
            }
          }
        }
      }
    }
  }
}

With team count 1 and maximum team size of 4, require up to 4 players per match.

Define multiple Profiles (Queues) for game modes specific rules and settings:

  • start with minimum of 4 players to keep players in queue and maximize match fill rate,

  • restrict matchmaking latency to prevent matching players far away,

  • let players choose a particular game difficulty to suit everybody’s skill level,

  • let players provide their map preferences to find a map suitable for everyone,

  • restrict player level difference to require similar degree of game progression,

  • specify backfill group size to replace leavers without exceeding server capacity,

  • use moderation flags to separate low-karma players and cheaters from general population,

  • Group Up for pre-made parties and to fill teams without exceeding server capacity,

  • allocate more CPU or memory using different 🏷️ App Versions for other profiles.

Start with the ideal conditions, and expand restrictions to ensure quick matches:

  • relax latency restrictions over time to find more players,

  • increase allowed player level difference to find more players,

  • decrease minimum team size to require less players and start the game sooner,

    • server may fill empty slots with AI teammates,

    • or Backfill Match to add players later,

  • set minimum team size to 1 to launch the game solo after 150s of queue time

🎈 Social Games

Social games focus on building connections and relationships between players through collaboration, communication, and shared experience. Support high number of players, maximize match fill rate, and align player preferences and gameplay habits. Replace players who leave, and ensure high 🟢 Connection Quality to provide a responsive player experience.

🎈 Social Game Example
{
  "version": "3.2.0",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "social-example": {
      "ticket_expiration_period": "3m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "attributes": {
              "team_count": 1,
              "min_team_size": 50,
              "max_team_size": 50
            },
            "type": "player_count"
          },
          "beacons": {
            "attributes": {
              "difference": 125,
              "max_latency": 150
            },
            "type": "latencies"
          },
          "selected_mode": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "moderation_flags": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "15": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            },
            "match_size": {
              "team_count": 1,
              "min_team_size": 20,
              "max_team_size": 50
            }
          },
          "30": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 10,
              "max_team_size": 50
            }
          },
          "150": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 1,
              "max_team_size": 50
            }
          }
        }
      }
    }
  }
}

With team count 1 (free for all) and maximum team size of 50, require up to 50 players per match.

Define Profiles (Queues) for game modes specific rules and settings:

  • restrict matchmaking latency to prevent matching players far away,

  • let players provide their game mode preferences and find a mode suitable for everyone,

  • specify backfill group size to replace leavers without exceeding server capacity,

  • use moderation flags to separate low-karma players and cheaters from general population,

  • Group Up for pre-made lobbies or to fill teams without exceeding server capacity,

  • allocate more CPU or memory using different 🏷️ App Versions for other profiles.

Start with the ideal conditions, and expand restrictions to ensure quick matches:

  • relax latency restrictions over time to find more players,

  • slowly decrease minimum team size to require less players and start the game sooner,

    • server may fill empty slots with AI players,

    • or Backfill Match to add players later,

  • set minimum team size to 1 to launch the game solo after 150s of queue time.

Last updated

Was this helpful?