Matchmaking Rules
A rule is a generic way of describing a logical goal-seeking behavior. Rules apply to different levels of the matchmaking logic: match-level and team-level. Match-level rules ensure the validity of the match they are defined in, while team-level rules ensure the validity of the team they are defined in.
Rule format
{
"Type": "RuleType",
"Source": "SourcePath",
"Not": true/false,
"EnableRule": true/false,
"Relaxations": [
{
Relaxation1,
Relaxation2
}
]
}
Field | Required | Type | Description |
---|---|---|---|
Type | Yes | string | The rule to apply. See the Supported rules table below. |
Source | Yes | string | The data source path. See Supported data sources. |
Reference | No | * | The reference to compare to. Not used by all rules. *Any type is valid. For example, string, bool, list and number. |
Not | No | boolean | Inverses the rule if set as true. Is false, if not provided. |
EnableRule | No | boolean | Disables the rule if set to false. Is true if not provided. This is usually used to disable or enable a rule by a relaxation. |
Relaxations | No | List<Relaxations> | The list of relaxations to apply. See Rule relaxations and triggers. |
Supported rules
Rule | Input | Description |
---|---|---|
Difference | Source: List<number> Reference: Number | Ensures that the difference between all values in a list is within a certain distance. |
Equality | Source: List<*> Reference: * (Optional) | Ensures that all values in the list are equal. *The reference is the input type defined in the source. |
LessThan | Source: Number Reference: Number | Ensures that the source value is less than the reference value. |
LessThanEqual | Source: Number Reference: Number | Ensures that the source value is less than or equal to the reference value. |
GreaterThan | Source: Number Reference: Number | Ensures that the source value is greater than the reference value. |
GreaterThanEqual | Source: Number Reference: Number | Ensures that the source value is greater than or equal to the reference value. |
InList | Source: * Reference: List<*> | Ensures that the source value is in the reference list. *The reference is the input type defined in the source. |
Intersection | Source: List<List<*>> Overlap: Number | Ensures that the list of given lists has a minimum intersection of the provided overlap number. |
Supported data sources
Data in all players
Custom data defined by each player in a ticket can be accessed by rules using Players.CustomData.{your_custom_field_name}
. These custom defined data are added to the tickets during creation by the client. Refer to Create a ticket for how to create a ticket.
QoS in all players
Quality of service data for each player in a ticket can be accessed by rules using Players.QoSResults.Latency
and Players.QoSResults.PacketLoss
. See Quality of Service.
Leaderboards
Server authoritative matchmaking is supported through integration with Unity Leaderboards.
Leaderboard data for each player can be accessed by rules using Players.CustomData.ExternalData.Leaderboard.Score
and Players.CustomData.ExternalData.Leaderboard.Tier
. When this data source is selected, an additional ExternalData
object that includes the Id
of the target leaderboard must be defined:
"ExternalData": {
"Leaderboard": {
"Id": "my-leaderboard"
}
}
Any available leaderboard data will be appended to incoming tickets automatically and will be considered according to the defined rules. If a player does not have data for the defined leaderboard, this player will be added to this leaderboard with a score of 0.
A leaderboard that does not have tiers enabled is not compatible with rules using tiers. All tickets that end up in this pool will fail to match.
Cloud Save
Server authoritative matchmaking is also supported through integration with Unity Cloud Save.
Cloud Save data for each player can be accessed by rules using Players.CustomData.ExternalData.CloudSave.{cloud_save_data_path}
. The {cloud_save_data_path}
is a period-delimited path to the value to be used in the rule. The first section of the data path will retrieve the Cloud Save item at that key. Any remaining sections of the data path will be used to traverse the retrieved item.
Cloud Save Key | Cloud Save Item | Data Path | Retrieved Value |
---|---|---|---|
Skill | 500 | Skill | 500 |
Maps | ["desert", "sea"] | Maps | ["desert", "sea"] |
Inventory | { "Apples": 10, "Bottles": 3 } | Inventory.Apples | 10 |
When the Cloud Save data source is selected, an optional ExternalData
object can be defined to configure its behavior.
"ExternalData": {
"CloudSave": {
"AccessClass": "Protected",
"Default": 0
}
}
The Access Class indicates from where the player data should be retrieved. The same key may have a different item stored for each Access Class. If no Access Class is provided, it will default to Protected
.
A default value can also be defined. This default value will be used when a player does not have a Cloud Save item at the specified data path. The data type of the default value must be compatible with the defined rule. For example, an Equality rule with a Reference data type of Number only allows a default value data type of Number, while an InList rule with a Reference data type of List<String> only allows a default value data type of String.
Any available Cloud Save data will be appended to incoming tickets automatically and will be considered according to the defined rules. If a player does not have data for the defined Cloud Save data path and there is no default value specified, the ticket will be incompatible with the rule definition.
Supported data operations
Some of the input provided on players custom data in the matchmaking ticket support operations in order to create rules on them.
Operation | Input | Output | Description |
---|---|---|---|
Count | List<*> | Number | Get the number of elements in the provided list. *Any type is valid. For example, string, bool, list and number. |
Median | List<Number> | Number | Get the median of the numbers in the provided list. |
Avg | List<Number> | Number | Get the average of the numbers in the provided list. |
Sum | List<Number> | Number | Get the sum of the numbers in the provided list. |
Min | List<Number> | Number | Get the minimum number from the provided list of numbers. |
Max | List<Number> | Number | Get the maximum number from the provided list of numbers. |
Examples
The following is an example of accessing the Skill field:
{ ..."Source": "Players.CustomData.Skill"... }
The following is an example of averaging the skill of all the players in a match/team:
{ ..."Source": "Players.CustomData.Skill.Avg"... }
Examples of supported rules
Difference
In the following example, depending on where the rule is placed (match level or team level), all players in a match or team are within 200 skill points of each other:
{
"Type": "Difference",
"Source": "Players.CustomData.Skill",
"Reference": 200
}
Equality
In the following example, a rule at the team level ensures that all players in the monster team selected this team:
{
"Type": "Equality",
"Source": "Players.CustomData.SelectedTeam",
"Reference": "Monster"
}
In the following example, a rule at the match level ensures that all players in the match have the same password:
{
"Type": "Equality",
"Source": "Players.CustomData.Password"
}
In the following example, a rule at the match level ensures that all players in the match are in the same skill bracket:
{
"Type": "Equality",
"Source": "Players.Custom.SkillBracket"
}
LessThanEqual
In the following example, a rule on the team level ensures that each team has a maximum of two medics:
{
"Type": "LessThanEqual",
"Source": "Players.CustomData.PreferMedic.Count",
"Reference": 2
}
GreaterThanEqual
In the following example, a rule at the match level ensures that all players in the match have a skill of at least 500:
{
"Type": "GreaterThanEqual",
"Source": "Players.CustomData.Skill",
"Reference": 500
}
InList
In the following example, a rule at the team level ensures that players are placed in the monster team if a monster character is chosen:
{
"Type": "InList",
"Source": "Players.CustomData.ChosenCharacter",
"Reference": [ "Monster1", "Monster2", "Monster3" ]
}
Intersection
In the following example, a rule at the match level ensures that all the players in the match have at least three preferred maps in common:
{
"Type": "Intersection",
"Source": "Players.CustomData.PreferredMaps",
"Overlap": 3
}
Leaderboard
In the following example, a rule at the team level ensures that all the players in the team have a leaderboard score within 300 of each other.
"TeamRules": [
{
"Name": "Score",
"Type": "Difference",
"Source": "Players.CustomData.ExternalData.Leaderboard.Score",
"ExternalData": {
"Leaderboard": {
"Id": "my-leaderboard"
}
},
"Reference": 300,
"Not": false,
"EnableRule": true
}
]
In the following example, a rule at the match level ensures that all the players in the match must be in the same leaderboard tier.
"MatchRules": [
{
"Name": "Tier",
"Type": "Equality",
"Source": "Players.CustomData.ExternalData.Leaderboard.Tier",
"ExternalData": {
"Leaderboard": {
"Id": "my-leaderboard"
}
},
"Not": false,
"EnableRule": true
}
]
Cloud Save
In the following example, a rule at the team level ensures that all the players in the team have at least one unlocked map in common. If a player does not have an item in Cloud Save with the key Maps
, they will be assigned ["starter"]
for the purposes of matchmaking. This value will not be persisted in Cloud Save.
"TeamRules": [
{
"Name": "Unlocked Maps",
"Type": "Intersection",
"Source": "Players.CustomData.ExternalData.CloudSave.Maps.Unlocked",
"ExternalData": {
"CloudSave": {
"AccessClass": "Protected",
"Default": ["starter"]
}
},
"Not": false,
"EnableRule": true,
"Overlap": 1
}
]