Skip to main content

Configure role-based matchmaking

Last updated on April 18, 2024

Overview

The AccelByte Gaming Services (AGS) Multiplayer service supports many gameplay and matchmaking use cases, including role-based matchmaking. Role-based matchmaking is a system employed in multiplayer online games to enhance the player experience by ensuring a more balanced and enjoyable gameplay environment. This approach involves assigning specific roles or responsibilities to players based on their preferred play styles, expertise, or the characters they choose in a game. The primary objective of role-based matchmaking is to create more cohesive and strategic team compositions. This leads to more fair and more competitive matches.

Prerequisites

Configure match ruleset

In this example, you are going to create a match ruleset to support moba-style games for 5v5 with three roles: DPS, Tank, and Healer. An Ideal team would consist of three DPS, one Tank, and one Healer. Players can submit their preference roles, and matchmaking will assign the role based on the player preference. The game will also consider the MatchMaking Rating (MMS) 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,
"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
}

For more information about rulesets, see Configure match rulesets section.

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 DPS, two Tank, and two Healer roles in the queue. Matchmaking will also consider the MMR stats with +/- 100 MMR difference at first and will expand to 150 in 20 seconds, then to 200 in 30 seconds. You must also add the region latency expansion rule that will start at 100ms (ping) range and will be expanded by 50ms every five seconds until the maximum range 1000ms is reached.

This simple role would work if there are enough players in the matchmaking queue who submit the role preference based on the matchmaking criteria: three DPS, one Healer, 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 DPS, two Tank, and two Healer roles 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 the inadequate roles in the queue problem 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 DPS on the team during game play.

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 DPS 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

In the AGS documentation, a matchmaking request is referred to 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, the Matchmaking service 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 Accelbyte 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 MMR attribute is used in the example ruleset, do not forget to configure the MMR in the statistic service. For more information, see skill-based matchmaking.