随着王者荣耀与吃鸡的游戏全民化,匹配也深入人心,对于多人竞技游戏,通常是多个人组成一组对抗对面的多个人,队伍的输赢跟你匹配的队友有密切的关系,也正是由于这种机制,很多人吐槽系统分给自己的队友真的是垃圾,一顿操作猛如虎,一看战绩0-5。一般来说,现在的匹配系统考虑的因素还算全面,之所以遇到垃圾队友,跟自己的关系很大,电子竞技,菜是原罪。
下面的内容是我平常学习到的一些匹配系统的知识整理,参考了一些内网的资料,主要包括:
最初的游戏比如象棋和围棋,有段位的概念,围棋职业选手分为从低到高九个段位等级,九段最高,地位大致相当于象棋界的特级大师;初段最低。ELO等级分制度是基于统计学的一个评估棋手水平的方法。1970年国际棋联正式开始使用等级分制度。
Elo,并不是一个缩写,而是系统发明者的姓。它本来是个改良的国际象棋积分系统,现在被广泛用于很多类比赛的选手分级。大部分游戏也使用了这套评分算法,比如星际,魔兽争霸3,魔兽世界,dota,LOL,守望先锋等等。
游戏里面,把匹配分作为玩家的一个属性,每次对局结算的时候根据本局玩家的表现,计算玩家的分数,看是加分还是减分,下次匹配的时候,把 匹配分 作为匹配队友和对手的重要指标,匹配旗鼓相当的人。
我们调取某知名吃鸡手游的单排开局玩家数与吃鸡者击杀玩家数的统计数据:
[参考lionxhli的数据]
可以看到数据几乎完美的吻合log2(人数)的曲线,从而证明了这个结论是可靠的:吃鸡难度为入局队伍数以2为底的对数。
取得第N名的难度,总人数M :
f(N) = \log_2{M} - \log_2{N}
那么根据总人数和排名得到的数字作为计算ELO的重要系数,结合新手加分,跑动,走位,一枪操作等其他条件,确定玩家的本场加减分。
类似的Moba游戏会参考人头数、推塔数,承受伤害、输出伤害、推塔数、经济等因素,确定符合游戏特点的分数模型。
对于一个实际工程中的匹配服务,在要考虑上面的限制因素基础上,要设计合适的数据结构和算法满足玩家组队对局,考虑匹配时间-实力接近-搭配合理-其他逻辑的平衡。
init(); // 初始化匹配队列
while(1)
{
RecvMatchReq(); // 接收匹配请求(取消匹配) 放到对应的匹配池
HandleMatch(); // 匹配,处理结果
}
finish();
匹配池是每个游戏类型匹配的基本单位,其中包含一个二维数组,数组的每个元素是一个含有五个元素的子数组,子数组的每个元素是一个队列。 二维数组的划分标准是ELO的大小,每10分一个分段,比如1536分在 arr[1536/10], 子数组是按照 人数划分的,比如 五人组队的在第一个队列,4人组队的在第二个队列……
匹配过程:
// 有一个全局模式表,表示匹配的模式及优先级 记为 mode_map
/*
5-5 //五个人组队匹配5个人组队的
4+1 vs 4+1
3+1 vs 3+2
5 vs 3+2
......
1+1+1+1+1 vs 1+1+1+1+1 // 五个单排的
*/
HandleMatch()
{
while(mode_map)
{
// 把ELO相同的人 组一队
// 处理 搭配等逻辑需求
}
// 每次处理 1000个请求,约 1 、2 ms
}
匹配系统的目标是 寻找两队旗鼓相当的人,从而开始一场体验好的对局。以前有过这样一个想法,现在的人好多都在抱怨找不到女/男朋友,如果类比于游戏,把一个人按照不同的指标换分,根据一个人的颜值、收入、身高、体重、地区、发型、爱好等打一个或者几个分数,按照每个人的需求给每个人匹配一个对应的对象,岂不美哉? 那时的我还年轻,考虑问题比较理想化,没有成本和平衡的概念。如果爱情能像游戏一样简单,这个社会会是多么美好??