Skip to Content
CrossingNet
匹配

匹配

队列、维度、Elo 窗口、多队与 Party:匹配器每秒做一次决定,决定的是谁和谁一组,不是谁进哪个房间。

匹配器只回答一个问题:现在队列里,哪些人应该被配成一组? 它不关心房间在哪、谁去开, 那是大厅的事。配好之后把这一组交给大厅:认领预热实例,或者新拉起一个。

队列里有什么

每个排队的人一张 ticket:

PlayerId  Mode  Elo  EnqueueTime  PartyId  TeamSize  FullPartyTeam  RecentOpponents
入口说明
ServerEnqueueMatch(Mode)客户端 RPC,单人入队
Matcher->Enqueue(PC, Mode, PartyId, EloOverride, bFullPartyTeam)服务端入口
Matcher->AutoParty(PC, PartySize, Mode)测试用:凑一个 N 人队
Matcher->CancelEnqueue(PC) / ServerCancelMatch()取消
GetQueueCount()当前人数

队列变化通过 OnQueueChanged 广播;每次入队都生成一条 trace。

维度

ICrossingMatchDimension 是扩展点:实现一个维度,注册进匹配器,它每一轮参与筛选。

Dimensions.Add(MakeShared<FMyRegionDimension>());
Dimensions.Add(MakeShared<FMyInputDeviceDimension>());

维度拿到候选集合,返回它能接受的子集;多个维度按注册顺序串联。常见维度:

维度用途
区域同区域才配(跨区延迟)
输入设备手柄/键鼠分开
段位模式排位与休闲分开池
预组队单排与多排是否同池

Elo 窗口

窗口不固定,随时间线性放宽:

MatchBaseEloWindow=100.0
MatchEloGrowthPerSecond=20.0
MatchMaxWaitSeconds=180.0
MatchTickSeconds=1.0

等待 0 秒窗口 ±100;等 3 秒 ±160;等到 MatchMaxWaitSeconds 还没配到,这张票判 6001 MatchTimeout 并从队列移除。

bAllowEloOverride 与 EloOverride 允许某个入口无视窗口(测试、活动局)。

模式

模式是一组容量参数:

+ModeConfigs=(Mode="1v1",TeamSize=1,TeamCount=2)
+ModeConfigs=(Mode="2v2",TeamSize=2,TeamCount=2)
+ModeConfigs=(Mode="3v3",TeamSize=3,TeamCount=2)
+ModeConfigs=(Mode="FFA4",TeamSize=1,TeamCount=4)
+ModeConfigs=(Mode="3T2",TeamSize=2,TeamCount=3)

FCrossingModeConfig 默认 1v1 / TeamSize=1 / TeamCount=2。 多队匹配走 TryFormMultiTeamMatches,胜负按队伍号(EndGameWithWinner(Reason, Team))。

模式还可以带阵营定义(Factions),为空时默认「阵营 = 队伍」。

预热池

bEnableWarmPool=False
WarmPoolMode=1v1
WarmPoolSize=1
WarmPoolCooldownSeconds=15.0

池里常备 Ready 空实例:匹配成立时 ClaimWarmInstance 认领,SETMATCH 写入 matchId, 等 CMD_ACK 后登记玩家。认领失败退回 SpawnInstance。

预热池是一次「把开局等待挪到配到之前」的交易:它让配到的人立刻进房,代价是空闲时也占着进程。 有 Bot 的对局不走预热池。

Party 整队

UCrossingPartySubsystem 管队伍,匹配器只看 PartyId:

能力服务端入口
建队CreateParty(PC)
加入 / 离开JoinParty(PC, PartyId)、LeaveParty(PlayerId, Reason)
踢人 / 移交队长KickMember(Leader, Target)、TransferLeader(Leader, Target)
模式 / 排位标记SetPartyMode、SetPartyRanked
准备SetMemberReady(PlayerId, bReady)
开始匹配StartPartyMatch(Leader)
赛后返回 / 再开ReturnFromMatch、Rematch
邀请InviteMember / AcceptInvite / DeclineInvite(30 秒 TTL)

客户端对应 RPC 在 ACrossingPlayerController(ServerCreateParty … ServerPartyRematch)。 队伍 Elo 取法:

PartyMatchEloMode=Max        ; Max / Average / Weighted
PartyCasualEloMode=Average
PartyMaxEloSpread=0
bFullPartyOnlyVsFullParty=False

bFullPartyOnlyVsFullParty=True 时满编队只撞满编队(王者的做法);Max 让高段位的人拉高整队匹配池。

Bot 补位

bEnableBotFill=False
BotFillSeconds=60.0
bBotFillRequireHumanEachSide=True

等太久就塞 Bot:bBotFillRequireHumanEachSide 保证两边都有真人。 Bot 也可以接管掉线玩家的座位(bBotTakeoverOnDisconnect),玩家回来时让位(BotReplaced)。

秒退惩罚

bEnableDodgePenalty=True
DodgeCooldownSeconds=60.0

离队/秒退后再入队会被挡 6006 PenaltyCooldown,ApplyDodgePenalty / IsOnDodgeCooldown 是查询与施加的入口。

匹配策略

默认 FGreedyWindowPolicy,按 Elo 窗口贪心配对。策略可替换:

Matcher->Policy = MakeShared<FMyPolicy>();   // 实现 IMatchPolicy

策略只决定「候选集合里选谁」,不负责拉起实例、不负责发票据。

事件

事件时机
OnQueueChanged队列人数变化
OnMatchFound配到一组
OnMatchFailed匹配失败(超时/取消/无实例)
OnReadyCheckStarted开始确认
OnAssignmentReceived收到分配(地址、端口、票据)

测试钩子

-CrossingNetAutoMatch       客户端进服后自动入队
-CrossingNetAutoReady       收到 ReadyCheck 自动确认
-CrossingNetAutoEndGame=8   房间 8 秒后自动结束
-CrossingNetMatchPolicySelfTest   策略自检(重叠候选去重)

下一页:身份与档案。

On this page