使用Unity Game Services实现ELO匹配
解读
面试官抛出这道题,核心想验证三件事:
- 你是否真正用过Unity Game Services(UGS)而不仅停留在“听过”层面;
- 能否把ELO算法与UGS的Matchmaker、Lobby、Relay三大模块无缝串起来,而不是各说各话;
- 对国内版号+实名+防沉迷合规环境下的分池、分段、分时段匹配策略有没有落地经验。
回答时务必把“ELO值如何存、如何算、如何同步”和“UGS哪条API负责哪一步”一一对应,让面试官一听就知道你独立上线过。
知识点
- UGS Matchmaker规则脚本(Rule Script)语法:必须会写bucket、attribute、expansion三段式,否则无法按ELO分段。
- ELO-K值动态曲线:国内竞技手游普遍用“K=40→16递减”模型,前端只算预测值,最终分值由Cloud Code二次校验防止客户端作弊。
- 属性同步顺序:Lobby创建时把PlayerElo写进Lobby Data → Matchmaker把该值映射到Queue Attribute → Relay分配服务器后通过NetworkManager.Singleton广播给房间。
- 合规分池:实名未成年玩家必须在规则脚本里加**"age<=18"独立bucket,且22:00-08:00时段直接返回matchmaking failed (1040)**,否则审核被打回。
- 性能红线:Matchmakerexpansion interval不得小于3s,否则国内低端安卓会出现**“匹配超时”**崩溃,被华为应用市场拒审。
答案
分五步落地,全部用UGS官方API,不自己搭服务器。
第一步:在Unity Dashboard新建**“EloQueue”**,规则脚本核心三行:
attributes {
playerElo: 1500..3000
}
bucket {
range: 100
expansion: 5s +50
}
range 100即±50分快速匹配,5秒后扩大到±100,兼顾速度与精度。
第二步:客户端Authentication成功后,把本地PlayerPrefs.GetInt("Elo",1500)写进Lobby Data:
var lobbyOptions = new CreateLobbyOptions{
Data = new Dictionary<string, DataObject>{
{"elo", new DataObject(DataObject.VisibilityOptions.Public, localElo.ToString())}
}
};
注意:DataObject只能存string,转int时先TryParse防崩。
第三步:调用MatchmakerService.StartMatchmakingAsync,把elo作为Attribute塞进去:
var matchmakingResponse = await MatchmakerService.StartMatchmakingAsync(
new MatchmakingPlayer{
Attributes = new Dictionary<string, object>{
{"playerElo", int.Parse(localElo)}
}
},
"EloQueue"
);
此时Matchmaker会按规则脚本自动分桶,无需客户端写任何排序逻辑。
第四步:匹配成功后拿到AllocationID,用Relay分配服务器:
var joinCode = await RelayService.GetJoinCodeAsync(allocation.AllocationId);
NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(
allocation.RelayServer.IpV4,
(ushort)allocation.RelayServer.Port,
allocation.AllocationIdBytes,
allocation.Key,
allocation.ConnectionData
);
Elo值随Lobby Data自动同步到房间内,开局即可做平衡队伍逻辑。
第五步:比赛结束,客户端只算预测分值,真正的Elo增减在Cloud Code里用K=30*(1-预测胜率)重新计算,再写回Cloud Save:
const k = 30;
const delta = Math.round(k * (actualScore - expectedScore));
await Data.Set("elo", newElo, playerId);
Cloud Code里还能顺手做连胜衰减、恶意挂机扣分,保证数值安全。
至此,零后端、全UGS、可过审的ELO匹配闭环完成。
拓展思考
- 如果项目要上字节小游戏渠道,Relay UDP会被企业防火墙拦截,需降级为WebGL + WebSocket,此时要把Matchmaker的allocation strategy改成**“WebGLOnly”并自建WebSocket中继**,否则匹配成功却连不上服务器。
- Elo与MMR双轨制:国内玩家对“星钻王者”段位更敏感,可在Cloud Code里维护hidden MMR做匹配,display rank只做展示,两值分离后降段保护和赛季重置更灵活。
- 实时校验:UGS的Rate Limit为100次/100秒/玩家,Elo更新必须走批量聚合(一局游戏只写一次),否则高频写会触发429导致玩家掉线,华为渠道审核会以此为由打回。