跳到主要内容

规则集示例

概述

PGOS的规则集可以覆盖多种匹配场景。以下示例展示了规则集结构和属性表达式语法。您可以复制这些规则集并根据需求进行自定义。 有关规则集编辑器和参考的更多信息,请参见以下链接:

示例1. 匹配MMR排名相近的玩家

本示例说明如何按照以下要求设置两支实力相当的玩家队伍:

  • 创建两支玩家队伍。
    • 尝试为每支队伍找到3名玩家。
    • 两支队伍的玩家人数相等。
  • 包含玩家的MMR值(如未提供,默认为1000)
  • 匹配MMR值相近的玩家。确保两支队伍的平均玩家技能差异在0.5分以内。
  • 如果匹配未能快速完成,放宽以下限制以在合理时间内完成匹配。
    • 5秒后,将队伍最小人数降至2人,MMR差异上限扩大到50。
    • 10秒后,将队伍最小人数降至1人,MMR差异上限扩大到100。
提示
  • 即使触发了扩展机制,匹配系统仍会尽量寻找最符合规则的匹配结果。它会努力填满队伍,并寻找 MMR 尽可能接近的玩家。但如果无法完全满足队伍要求,且 MMR 差异在每条规则的最低限制范围内,匹配系统最终会输出该匹配结果。
  • 由于两个队伍结构相同,您可以选择只创建一个队伍定义并将队伍数量设为 2。在这种情况下,如果您将 red 队伍的数量设为 2,输出的队伍将被命名为 red_001red_002
  • 当您不确定所写表达式的输出结果时,可以随时在规则集调试器中进行验证。- 当您不确定所编辑规则集的效果时,可以随时使用匹配模拟器来模拟整个匹配过程。
{
"version":"v1.0",
"playerAttributes":[
{
"name":"mmr",
"type":"number",
"default":1000
}
],
"teams":[
{
"name":"red",
"maxPlayers":3,
"minPlayers":3
},
{
"name":"blue",
"maxPlayers":3,
"minPlayers":3
}
],
"rules":[
{
"name":"mmr_calc",
"type":"distanceRule",
// get mmr values for players in each team, and flatten into a one-dimension list
"measurements":[
"flatten(teams[*].players.playerAttributes[mmr])"
],
// get the average mmr for all players
"referenceValue":"avg(flatten(teams[*].players.playerAttributes[mmr]))",
"minDistance":0,
"maxDistance":0.5
},
{
"name":"equal_team_size",
"type":"comparisonRule",
// get the size of blue team
"measurements":[
"count(teams[blue].players)"
],
// compare with the size of red team
"referenceValue":"count(teams[red].players)",
"operation":"="
}
],
"expansions":[
{
// select the minPlayers of each team
"target":"teams[*].minPlayers",
"steps":[
{
"waitTimeSeconds":5,
"value":2
},
{
"waitTimeSeconds":15,
"value":1
}
]
},
{
// select the maxDistance of specific rule
"target":"rules[mmr_calc].maxDistance",
"steps":[
{
"waitTimeSeconds":5,
"value":50
},
{
"waitTimeSeconds":15,
"value":100
}
]
}
]
}

示例 2. 根据玩家选择的地图进行分组

本示例演示如何按照以下要求设置可变数量的队伍:

  • 创建 10~20 个玩家队伍。

    • 每个队伍包含 3~4 名玩家。
    • 最终的队伍必须拥有相同数量的玩家。
    • 根据匹配中的玩家数量确定队伍数量,范围在 10~20 个之间。
    • 队伍将按照 team_001team_002team_003 等方式命名。
  • 包含玩家的地图名称(如未提供则默认为空)

  • 选择选择相同地图的玩家。

  • 如果匹配未能快速完成,放宽队伍数量要求以在合理时间内完成匹配。

    • 10 秒后,将最小队伍数量降低至 8。

    • 30 秒后,将最小队伍数量降低至 5。

提示

map_binding 规则确保玩家具有相同的 map 属性。 在匹配系统内部,玩家属性将被索引以优化匹配器根据动态需求选择票据的性能。规则集不仅在玩家分组时进行检查,还会在匹配过程中应用。 匹配器使用线性规划方法来减少匹配所需的时间成本,在面对大量玩家时表现良好。

{
"version":"v1.0",
"playerAttributes":[
{
"name":"map",
"type":"string",
"default":""
}
],
"teams":[
{
"name":"team",
"maxPlayers":4,
"minPlayers":3,
"maxQuantity":20,
"minQuantity":10
}
],
"rules":[
{
"name":"map_binding",
"type":"comparisonRule",
// get the map of players in each team and flatten into a one-dimension list
"measurements":[
"flatten(teams[*].players.playerAttributes[map])"
],
// the map of these players must be the same
"operation":"="
},
{
"name":"equal_team_size",
"type":"comparisonRule",
// get the size of each team, as a one-dimension list
"measurements":[
"count(teams[*].players)"
],
// the size of each team must be the same
"operation":"="
}
],
"expansions":[
{
// select the minQuantity of each team
"target":"teams[*].minQuantity",
"steps":[
{
"waitTimeSeconds":10,
"value":8
},
{
"waitTimeSeconds":30,
"value":5
}
]
}
]
}

##示例 3. 预制队优先与其他预制队匹配 本示例说明如何优先匹配人数相同的预制队,并放宽时间限制,让群组玩家和单人玩家混合在一起。

  • 创建 4 支玩家队伍。
    • 每支队伍有 4 名玩家。
    • 变量队伍将被命名为 team_001team_002team_003team_004
  • 包含一个名为 partysize 的属性 ,即群组的大小。
  • 预制队将优先与其他预制队匹配。
  • 尝试将 4 人预制队与其他 4 人预制队匹配,将 2 人预制队与其他 2 人预制队匹配。该规则也适用于单人玩家,因此单人玩家应该与其他单人玩家匹配。
    • 30 秒后,放宽预制队规模差异的上限为 1,让 2 人预制队和单人玩家一起匹配。
    • 60 秒后,将预制队伍规模差异的上限放宽至 2,以便 4 人预制队伍和 2 人预制队伍可以一起匹配。
    • 90 秒后,将预制队伍规模差异的上限放宽至 3,以便理论上随机混合预制队伍和非预制队伍。
提示

请注意,partysize 由游戏客户端提供,可能会影响最终的匹配结果。对于单人玩家,该值应为 1,对于双人玩家,该值应为 2,对于四人玩家,该值应为 4

{
"version": "v1.0",
"playerAttributes": [
{
// the value should be the party size when premade team players enter matchmaking
"name": "partysize",
"type": "number",
"default": 1
}
],
"teams": [
{
"name": "team",
"minPlayers": 4,
"maxPlayers": 4,
"minQuantity": 4,
"maxQuantity": 4
}
],
"rules": [
{
"name": "partyRule",
"type": "distanceRule",
// get the max party size of existing premade teams
"measurements": [
"max(flatten(teams[*].players.playerAttributes[partysize]))"
],
// get the min party size of existing premade teams
"referenceValue": "min(flatten(teams[*].players.playerAttributes[partysize]))",
// limit the difference of party size close to zero
"maxDistance": 0.1,
"partyAggregation": "max"
}
],
"expansions": [
{
// relax the difference of party size to let premade teams and non-premade teams match together
"target": "rules[partyRule].maxDistance",
"steps": [
{
"waitTimeSeconds": 30,
"value": 1
},
{
"waitTimeSeconds": 60,
"value": 2
},
{
"waitTimeSeconds": 90,
"value": 3
}
]
}
]
}

示例 4. 允许特定范围的玩家数量并平均限制队伍大小

本示例说明如何在开发阶段让少量玩家一起匹配。

  • 创建四个4人队伍。
  • 规则集应允许4~16名玩家一起匹配,而不是分散在多个对局中。

如果直接将每个队伍的 minPlayers 设置为 1,当8名玩家陆续进入匹配时,有一定概率这8名玩家会被分成两个对局,每个对局包含4名玩家。这是因为 minPlayers1,且当匹配器工作时,一些后进入匹配的玩家可能不在票据池中。

提示

因此在这种场景下,让4~16名玩家一起匹配的安全方法是利用扩展机制,在玩家陆续进入匹配之间创建一个可容忍的时间。

{
"version": "v1.0",
"playerAttributes": [],
"teams": [
{
"name": "A",
"minPlayers": 4,
"maxPlayers": 4
},
{
"name": "B",
"minPlayers": 4,
"maxPlayers": 4
},
{
"name": "C",
"minPlayers": 4,
"maxPlayers": 4
},
{
"name": "D",
"minPlayers": 4,
"maxPlayers": 4
}
],
"rules": [],
"expansions": [
{
// select the minPlayers of each team
"target": "teams[*].minPlayers",
"steps": [
{
"waitTimeSeconds": 30,
"value": 3
},
{
"waitTimeSeconds": 60,
"value": 2
},
{
"waitTimeSeconds": 90,
"value": 1
}
]
}
]
}

示例 5. 匹配三支不同阵营的队伍

本示例说明如何在匹配中设置不同阵营。

  • 创建三支队伍,每支队伍有四名玩家。
  • 包含玩家的 MMR 值(如未提供,默认为 1000)。
  • 包含玩家的阵营值(应为 ghosthuman
  • 其中两支队伍为 human 阵营,一支队伍为 ghost 阵营。
{
"version": "v1.0",
"playerAttributes": [
{
"name": "level",
"type": "number",
"default": 0
},
{
"name": "side",
"type": "string",
"default": ""
}
],
"teams": [
{
"name": "red",
"minPlayers": 3,
"maxPlayers": 3
},
{
"name": "green",
"minPlayers": 10,
"maxPlayers": 10
},
{
"name": "blue",
"minPlayers": 10,
"maxPlayers": 10
}
],
"rules": [
{
"name": "mmr_calc",
"type": "distanceRule",
// get mmr values for players in each team, and flatten into a one-dimension list
"measurements": [
"flatten(teams[*].players.playerAttributes[level])"
],
// get the average mmr for all players
"referenceValue": "avg(flatten(teams[*].players.playerAttributes[level]))",
"maxDistance": 3
},
{
"name": "side_binding",
"type": "comparisonRule",
// get the side value of each team, as a two-dimension list
// inside the two-dimension list, the sides inside a team must be the same
// feel free to validate the possible result of your expression using `ruleset debugger`
"measurements": [
"teams[*].players.playerAttributes[side]"
],
"operation": "="
},
{
"name": "side_binding_red",
"type": "comparisonRule",
// get the side value of red team, as a one-dimension list
"measurements": [
"teams[red].players.playerAttributes[side]"
],
// red team are all attackers
"referenceValue": "ghost",
"operation": "="
},
{
"name": "side_binding_green",
"type": "comparisonRule",
// get the side value of green team, as a one-dimension list
"measurements": [
"teams[green].players.playerAttributes[side]"
],
// green team are all attackers
"referenceValue": "human",
"operation": "="
},
{
"name": "side_binding_blue",
"type": "comparisonRule",
// get the side value of blue team, as a one-dimension list
"measurements": [
"teams[blue].players.playerAttributes[side]"
],
// blue team are all attackers
"referenceValue": "human",
"operation": "="
}
],
"expansions": []
}

示例 6. 大逃杀

本示例说明如何设置具有可变数量队伍的规则。

  • 创建一支包含4名玩家的队伍
  • 将队伍数量限制在10~20支之间
  • 随着时间推移逐步放宽限制,允许较少的队伍进行对战
{
"version": "v1.0",
"playerAttributes": [],
"teams": [
{
"name": "squad",
"minPlayers": 4,
"maxPlayers": 4,
"minQuantity": 10,
"maxQuantity": 20
}
],
"rules": [],
"expansions": [
{
"target": "teams[squad].minQuantity",
"steps": [
{
"waitTimeSeconds": 30,
"value": 7
},
{
"waitTimeSeconds": 50,
"value": 5
},
{
"waitTimeSeconds": 70,
"value": 3
}
]
}
]
}

示例 7. 将短时间内发起匹配的玩家匹配到同一场战斗中

此示例说明如何使用“扩展”功能将短时间内开始匹配的玩家分组到同一场比赛中。

  • 本规则要求每场战斗有 1~6 名玩家
  • 限制团队至少由 6 名玩家组成
  • 逐渐将限制从 6 人扩大到 1 人
提示

如果将 minPlayers 配置设置为 1 而不使用 expansion 功能,则匹配算法将立即启动并为第一个发起匹配的玩家生成一个满足 minPlayers 要求的游戏会话。即使尝试回填以将后续玩家添加到游戏会话中,也存在生成新游戏会话并回填旧游戏会话的趋势,这不能保证所有新玩家都会回填到旧游戏会话中。

通过使用扩展功能,首先发起匹配的玩家可以短暂等待,并在短时间内与其他发起匹配的玩家开始游戏。

{
"version": "v1.0",
"playerAttributes": [],
"teams": [
{
"name": "SoloTeam",
"minPlayers": 6,
"maxPlayers": 6,
"minQuantity": 1,
"maxQuantity": 1
}
],
"rules": [],
"expansions": [
{
"target": "teams[SoloTeam].minPlayers",
"steps": [
{
"waitTimeSeconds": 1,
"value": 5
}
]
},
{
"target": "teams[SoloTeam].minPlayers",
"steps": [
{
"waitTimeSeconds": 2,
"value": 4
}
]
},
{
"target": "teams[SoloTeam].minPlayers",
"steps": [
{
"waitTimeSeconds": 3,
"value": 3
}
]
},
{
"target": "teams[SoloTeam].minPlayers",
"steps": [
{
"waitTimeSeconds": 4,
"value": 2
}
]
},
{
"target": "teams[SoloTeam].minPlayers",
"steps": [
{
"waitTimeSeconds": 5,
"value": 1
}
]
}
]
}

示例 8. 多模式、多映射 匹配

本例演示如何实现多模式、多映射 匹配 。要求如下:

  • 玩家发起匹配时,可以从 3 种模式、n 张地图中选择,并允许多次选择。
  • 3 种游戏模式玩法不同,在匹配规则中体现为不同的队伍结构。
  • 模式 1 为两队 PvP,每队 2 名玩家。
  • 模式 2 为单队 PvE,总共 4 到 8 名玩家。
  • 模式 3 为大逃杀,有 m 个队,每队 4 名玩家,但 m 的范围是 4 到 8 名。
  • 映射选择不影响队伍结构。

要使用规则集实现这些要求,可以采用以下方法:

  • 用基于bit的数字表示玩家选择的不同地图。为每个映射分配一个数字,每个bit代表该映射是否被选中,并将其商店为“ 映射 ”属性。然后编写一个表达式对“ 映射 ”属性进行按位与运算,创建一个比较规则,要求结果大于零。这确保所有玩家选择的地图都有交集。
  • 对于 3 种游戏模式,定义三个规则集并创建一个 MatchConfig。为每个规则集分配一个单独的Placer ,将它们放置在不同的 Fleets 上以支持不同的游戏玩法。由于不同的游戏模式具有不同的在线玩家数量,因此混合 Fleets 有助于提高资源利用率。
    提示

    有几点需要注意:

  • 在bit-wise运算中使用数字类型属性时,将 bitmap 字段设置为 true。
  • 由于不同的模式具有不同的团队结构,因此需要多个规则集,并且每个模式具有唯一的属性。当客户端选择模式时,设置相应的属性。
  • 将多个规则集关联到匹配配置时,所有规则集必须共享相同的玩家属性定义。

:::

子规则集 1

{
"version": "v1.0",
"playerAttributes": [
{
"name": "map",
"type": "number",
"bitmap": true,
"default": 0
},
{
"name": "mode1",
"type": "number",
"bitmap": false,
"default": 0
},
{
"name": "mode2",
"type": "number",
"bitmap": false,
"default": 0
},
{
"name": "mode3",
"type": "number",
"bitmap": false,
"default": 0
}
],
"teams": [
{
"name": "red",
"minPlayers": 2,
"maxPlayers": 2,
"minQuantity": 1,
"maxQuantity": 1
},
{
"name": "blue",
"minPlayers": 2,
"maxPlayers": 2,
"minQuantity": 1,
"maxQuantity": 1
}
],
"rules": [
{
"name": "map_intersection",
"type": "comparisonRule",
"description": "",
"measurements": [
"and(flatten(teams[*].players.playerAttributes[map]))"
],
"referenceValue": "0",
"operation": ">"
},
{
"name": "mode_selection",
"type": "comparisonRule",
"description": "",
"measurements": [
"flatten(teams[*].players.playerAttributes[mode1])"
],
"referenceValue": "1",
"operation": "="
}
],
"expansions": []
}

子规则集 3

{
"version": "v1.0",
"playerAttributes": [
{
"name": "map",
"type": "number",
"bitmap": true,
"default": 0
},
{
"name": "mode1",
"type": "number",
"bitmap": false,
"default": 0
},
{
"name": "mode2",
"type": "number",
"bitmap": false,
"default": 0
},
{
"name": "mode3",
"type": "number",
"bitmap": false,
"default": 0
}
],
"teams": [
{
"name": "one",
"minPlayers": 4,
"maxPlayers": 8,
"minQuantity": 1,
"maxQuantity": 1
}
],
"rules": [
{
"name": "map_intersection",
"type": "comparisonRule",
"description": "",
"measurements": [
"and(flatten(teams[*].players.playerAttributes[map]))"
],
"referenceValue": "0",
"operation": ">"
},
{
"name": "mode_selection",
"type": "comparisonRule",
"description": "",
"measurements": [
"flatten(teams[*].players.playerAttributes[mode2])"
],
"referenceValue": "1",
"operation": "="
}
],
"expansions": []
}

Sub Ruleset 3

{
"version": "v1.0",
"playerAttributes": [
{
"name": "map",
"type": "number",
"bitmap": true,
"default": 0
},
{
"name": "mode1",
"type": "number",
"bitmap": false,
"default": 0
},
{
"name": "mode2",
"type": "number",
"bitmap": false,
"default": 0
},
{
"name": "mode3",
"type": "number",
"bitmap": false,
"default": 0
}
],
"teams": [
{
"name": "one",
"minPlayers": 4,
"maxPlayers": 4,
"minQuantity": 4,
"maxQuantity": 8
}
],
"rules": [
{
"name": "map_intersection",
"type": "comparisonRule",
"description": "",
"measurements": [
"and(flatten(teams[*].players.playerAttributes[map]))"
],
"referenceValue": "0",
"operation": ">"
},
{
"name": "mode_selection",
"type": "comparisonRule",
"description": "",
"measurements": [
"flatten(teams[*].players.playerAttributes[mode3])"
],
"referenceValue": "1",
"operation": "="
}
],
"expansions": []
}

然后创建一个匹配配置并添加这三个规则集。