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
    }
  ]
}
FieldRequiredTypeDescription
TypeYesstringThe rule to apply. See the Supported rules table below.
SourceYesstringThe data source path. See Supported data sources.
ReferenceNostring, number or array*The reference to compare to. Not used by all rules. *Valid reference types depend on rule type.
NotNobooleanInverses the rule if set as true. Is false, if not provided.
EnableRuleNobooleanDisables the rule if set to false. Is true if not provided. This is usually used to disable or enable a rule by a relaxation.
RelaxationsNoList<Relaxations>The list of relaxations to apply. See Rule relaxations and triggers.

Supported rules

RuleInputDescription
DifferenceSource: List<number>

Reference: Number
Ensures that the difference between all values in a list is within a certain distance.
EqualitySource: List<string or number>

Reference: string or number*
Ensures that all values in the list are equal.

*The reference is the input type defined in the source.
LessThanSource: Number

Reference: Number
Ensures that the source value is less than the reference value.
LessThanEqualSource: Number

Reference: Number
Ensures that the source value is less than or equal to the reference value.
GreaterThanSource: Number

Reference: Number
Ensures that the source value is greater than the reference value.
GreaterThanEqualSource: Number

Reference: Number
Ensures that the source value is greater than or equal to the reference value.
InListSource: string or number

Reference: List<string or number>
Ensures that the source value is in the reference list.

*The reference is the input type defined in the source.
IntersectionSource: List<List<string or number>>

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 KeyCloud Save ItemData PathRetrieved Value
Skill500Skill500
Maps["desert", "sea"]Maps["desert", "sea"]
Inventory{ "Apples": 10, "Bottles": 3 }Inventory.Apples10

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.

OperationInputOutputDescription
CountList<*>NumberGet the number of elements in the provided list. *Any type is valid. For example, string, bool, list and number.
MedianList<Number>NumberGet the median of the numbers in the provided list.
AvgList<Number>NumberGet the average of the numbers in the provided list.
SumList<Number>NumberGet the sum of the numbers in the provided list.
MinList<Number>NumberGet the minimum number from the provided list of numbers.
MaxList<Number>NumberGet 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 // Valid types: number
}

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" // Valid types: string or number
}

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 // Valid types: number
}

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 // Valid types: number
}

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" ] // Valid types: List<string> or List<number>
}

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 
}

In the following example, a rule at the match level ensures that all the players in the match have at least one of the items in the reference list:

{ 
   "Type": "Intersection", 
   "Source": "Players.CustomData.Items", 
   "Overlap": 1,
   "Reference": [ "PluePill", "RedPill" ] // Valid types: List<string> or List<number>
}

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
    }
]