Skip to main content

Configure role-based matchmaking

Last updated on October 24, 2024

Overview

AccelByte Gaming Services (AGS) Matchmaking supports role-based matchmaking. Role-based matchmaking allows players to match and play games based on their chosen "role" (e.g., tank, healer, or damage dealer [AKA damage per second, or DPS]). This article will show you how to configure role-based matchmaking.

Prerequisites

Configure match ruleset

In this example, you are going to create a match ruleset to support a style of game similar to a multiplayer online battle area (MOBA). The ruleset will be configured for competitive 5 vs. 5 with three available roles: tank, healer, and DPS. An ideal team would consist of three DPSs, one tank, and one healer. Players can submit their role preference and matchmaking will assign them the role based on their preference. The game will also consider the matchmaking rating (MMR) stats and player latencies in the ruleset. Here is an example:

{
"auto_backfill": true,
"alliance": {
"min_number": 2,
"max_number": 2,
"player_min_number": 5,
"player_max_number": 5,
"matching_rule": [
{
"attribute": "mmr",
"criteria": "distance",
"reference": 100
}
],
"combination": {
"has_combination": true,
"alliances": [
[
{
"name": "dps",
"min": 3,
"max": 3
},
{
"name": "tank",
"min": 1,
"max": 1
},
{
"name": "healer",
"min": 1,
"max": 1
}
]
]
}
},
"flexing_rule": [
{
"duration": 20,
"attribute": "mmr",
"criteria": "distance",
"reference": 150
},
{
"duration": 30,
"attribute": "mmr",
"criteria": "distance",
"reference": 200
}
],
"region_expansion_rate_ms": 5000,
"region_expansion_range_ms": 50,
"region_latency_initial_range_ms": 100,
"region_latency_max_ms": 1000
}

The combination rule for creating role-based matchmaking has the following objects:

  • has_combination: indicates that matchmaking has a combination and will use role-based matchmaking.
  • alliances: specifies the available roles for matchmaking and the required number of each role:
    • name: specifies the role name.
    • min: specifies the minimum number of the role to start a match.
    • max: specifies the maximum number of the role in a match.
note

Using the sample match ruleset above, the matchmaking will start looking for 10 players consisting of six DPSs, two tanks, and two healers in the queue. Matchmaking will also consider the matchmaking rating (MMR) stats with +/- 100 matchmaking rating (MMR) difference at first, and will expand to 150 after 20 seconds, then to 200 in 30 seconds. You must also add the region latency expansion rule that will start at 100 millisecond (ms) (ping) range and will be expanded by 50 ms every five seconds until the maximum range of 1000 ms is reached.

This sample role configuration would work if there are enough players in the matchmaking queue who submit the role preference based on the matchmaking criteria: three DPSs, one healer, and one tank. If there are enough players but not enough required roles in the queue, matchmaking cannot start and the player will fail to find a match until the required roles are available or the matchmaking ticket expires. To solve this, you can add role flexing to enable the matchmaking service to start a match by randomly assigning roles to the available players to meet the ruleset criteria. Players might get a role outside their preference if role flexing is applied. This ruleset would look like this:

{
"auto_backfill": true,
"alliance": {
"min_number": 2,
"max_number": 2,
"player_min_number": 5,
"player_max_number": 5,
"matching_rule": [
{
"attribute": "mmr",
"criteria": "distance",
"reference": 100
}
],
"combination": {
"role_flexing_enable": true,
"role_flexing_second": 20,
"role_flexing_player": 2,
"has_combination": true,
"alliances": [
[
{
"name": "dps",
"min": 3,
"max": 3
},
{
"name": "tank",
"min": 1,
"max": 1
},
{
"name": "healer",
"min": 1,
"max": 1
}
]
]
}
},
"flexing_rule": [
{
"duration": 20,
"name": "mmr",
"criteria": "distance",
"reference": 150
},
{
"duration": 30,
"name": "mmr",
"criteria": "distance",
"reference": 200
}
],
"region_expansion_rate_ms": 5000,
"region_expansion_range_ms": 50,
"region_latency_initial_range_ms": 100,
"region_latency_max_ms": 1000
}

Next, add the role flexing rule into your sample ruleset:

  • role_flexing_enable: this rule is to enable the flexing role for the available player. When a certain time passes and there are no available roles in the queue, matchmaking will randomly assign the required roles to start a match with the available players.
  • role_flexing_second: specifies the amount of time (in seconds) that must pass before matchmaking assigns a random role to the available players in the queue.
  • role_flexing_player: specifies the number of players that will get a random role.
note

Using the improved ruleset, the matchmaking service will still start looking for 10 players consisting of six DPSs, two tanks, and two healers in the queue. After 20 seconds, when the required roles are not met, matchmaking will assign roles randomly to the available players in the queue to fill the missing roles required to start the match.

You can solve for inadequate roles in the queue with role flexing. However, if there are not enough players in the queue, you can solve this issue by adding more flexing in the alliance teams number into the ruleset. You can decrease the required number of roles to start a match or even reduce the minimum players in each team.

Next, adjust the sample ruleset to allow the match to commence with a minimum of three players per team after 60 seconds. As for the role combination, reduce the minimum DPS role to one after 60 seconds. The ruleset would look like this:

{
"auto_backfill": true,
"alliance": {
"min_number": 2,
"max_number": 2,
"player_min_number": 5,
"player_max_number": 5,
"matching_rule": [
{
"attribute": "mmr",
"criteria": "distance",
"reference": 100
}
],
"combination": {
"role_flexing_enable": true,
"role_flexing_second": 20,
"role_flexing_player": 2,
"has_combination": true,
"alliances": [
[
{
"name": "dps",
"min": 3,
"max": 3
},
{
"name": "tank",
"min": 1,
"max": 1
},
{
"name": "healer",
"min": 1,
"max": 1
}
]
]
}
},
"alliance_flexing_rule": [
{
"duration": 60,
"min_number": 2,
"max_number": 2,
"player_min_number": 3,
"player_max_number": 5,
"combination": {
"role_flexing_enable": true,
"role_flexing_second": 20,
"role_flexing_player": 2,
"has_combination": true,
"alliances": [
[
{
"name": "dps",
"min": 1,
"max": 3
},
{
"name": "tank",
"min": 1,
"max": 1
},
{
"name": "healer",
"min": 1,
"max": 1
}
]
]
}
}
],
"flexing_rule": [
{
"duration": 20,
"name": "mmr",
"criteria": "distance",
"reference": 150
},
{
"duration": 30,
"name": "mmr",
"criteria": "distance",
"reference": 200
}
],
"region_expansion_rate_ms": 5000,
"region_expansion_range_ms": 50,
"region_latency_initial_range_ms": 100,
"region_latency_max_ms": 1000
}
note

After you add the alliance flexing rule, if there aren't enough players in the queue after 60 seconds, then the match can be started with a minimum of six players with one DPS, one tank, and one healer for each team. And, since you also set auto_backfill to true in your ruleset, matchmaking can still add more players to fill the missing DPSs on the team during gameplay.

Using the alliance flexing rule, you can adjust the role composition for each team as needed. For example, if after 90 seconds, not enough players are in the queue, you can change the mode to be 4v4 and modify the team composition to open up a possibility to have more tank roles than DPSs in the teams.

// Sample ruleset is still the same, but shows the alliance flexing rule as an example
...
"alliance_flexing_rule": [
{
"duration": 90,
"min_number": 2,
"max_number": 2,
"player_min_number": 4,
"player_max_number": 4,
"combination": {
"role_flexing_enable": true,
"role_flexing_second": 20,
"role_flexing_player": 2,
"has_combination": true,
"alliances": [
[
{
"name": "dps",
"min": 1,
"max": 2
},
{
"name": "tank",
"min": 1,
"max": 2
},
{
"name": "healer",
"min": 1,
"max": 1
}
]
]
}
}
]
...

Request matchmaking with role preferences

note

The AGS documentation refers to a matchmaking request as a "match ticket".

Players can configure a role preference in the player session attributes. The role preference will be used when there are no role attributes when submitting a match ticket. The following is an example payload for configuring the role preferences in the player session attributes:

POST /session/v1/public/namespaces/{namespace}/users/me/attributes

{
"roles": [
"dps",
"tank"
]
}
// AccelByte Unreal OSS Sample
// TO FOLLOW

With the example above, players set the DPS and tank roles as the main role preferences in the game. If there are no role attributes in the match ticket, AGS Matchmaking will consider the roles in the player attributes during the matchmaking process.

Role preference can also be set directly by the game client when submitting a match ticket. The following is an example payload for adding the the role preferences when submitting a match ticket:

POST /match2/v1/namespaces/{namespace}/match-tickets

{
"matchPool": "matchpool_name",
"attributes": {
"role": {
// The key is using the AGS userId of the player
"69174d0186f34445b681b8a6e928b64b": [
"dps",
"tank"
]
}
},
"latencies": {
"us-west-1": 35,
"us-east-2": 83,
"ap-northeast-1": 139,
"eu-central-1": 158,
"eu-west-1": 165,
"ap-southeast-2": 164,
"sa-east-1": 198,
"ap-southeast-1": 211
},
"sessionId": ""
}

By initializing a new variable, such as UserIdToRoleMap, you can easily define and map all users involved in the matchmaking process. Simply input the user's ID as the key and their role as the value in the search handle's query settings.

const FOnlineSubsystemAccelByte* OnlineSubsystem = static_cast<FOnlineSubsystemAccelByte*>(IOnlineSubsystem::Get(ACCELBYTE_SUBSYSTEM));
ensure(OnlineSubsystem != nullptr);
const FOnlineSessionAccelBytePtr SessionInterface = StaticCastSharedPtr<FOnlineSessionV2AccelByte>(OnlineSubsystem->GetSessionInterface());
ensure(SessionInterface != nullptr);

TSharedRef<FOnlineSessionSearch> SearchHandle = MakeShared<FOnlineSessionSearch>();
const FString MatchPoolName = "match_pool_name";
SearchHandle->QuerySettings.Set(SETTING_SESSION_MATCHPOOL, MatchPoolName, EOnlineComparisonOp::Equals);

// Set user role attributes
TMap<FString, TArray<FString>> UserIdToRoleMap{};
UserIdToRoleMap.Add("69174d0186f34445b681b8a6e928b64b", {"dps", "tank"});
for (auto UserId : UserIdToRoleMap)
{
const FName SettingKey = FName(UserId.Key);
const TArray<FString> SettingValue = UserId.Value;
FOnlineSearchSettingsAccelByte::Set(SearchHandle->QuerySettings, SettingKey, SettingValue, EOnlineComparisonOp::Equals);
}

const FOnStartMatchmakingComplete OnStartMatchmakingCompleteDelegate = FOnStartMatchmakingComplete::CreateLambda(
[](FName SessionName, const struct FOnlineError& ErrorDetails, const struct FSessionMatchmakingResults& Results){
// On Start Matchmaking Complete
});

if (!SessionInterface->StartMatchmaking(USER_ID_TO_MATCHMAKING_USER_ARRAY(LocalUserId.ToSharedRef()), NAME_GameSession, FOnlineSessionSettings(), SearchHandle, OnStartMatchmakingCompleteDelegate))
{
// Return false
}

In the match ticket role attributes, the key is to use the userId of the player. The role attributes in the match ticket will take precedence over the roles in the player session attributes. You can set the roles preference either on the match ticket attributes or only on the player session attributes. However, when you set the role preference in both, the role attributes in the match ticket will be used.

note

Since the matchmaking rating (MMR) attribute is used in the example ruleset, do not forget to configure the MMR in AGS Statistics. For more information, see skill-based matchmaking.