抽卡/抽奖系统
概述
抽卡是社交休闲游戏的核心变现玩法,也是信任要求最高的系统:概率是否真实、保底是否兑现,直接关系口碑与合规。抽卡系统的难点有四:概率表配置(多档位、可运营调整)、保底机制(软保底/硬保底的状态管理)、概率验证(服务端随机种子可复现)、记录与公示(玩家可查、可举证)。本文设计完整的抽卡系统。
一、概率表配置
1.1 概率模型
GachaPool(配置表):
poolId、名称、单抽价格、十连价格
items(奖池条目:itemId + 权重/概率)
rateType(权重 or 百分比)
guarantee(保底配置)
priceCurrency、priceAmount
抽奖条目:
按稀有度分层:普通 > 稀有 > 史诗 > 传说
每层内按权重分配具体道具概率计算:
权重法:条目概率 = 条目权重 / 总权重
分层法:先按层概率抽层,再在层内抽条目
服务器运行时可调整(配置热更新)1.2 概率合规
合规要求(国内):
公布真实概率(每档公示)
公示需与实际实现一致
概率配置留档,运营可审计概率表校验:
总概率 = 100%(配置加载时校验)
保底不改变公示概率(保底是额外机制)
公示信息随配置热更同步更新二、保底机制
2.1 硬保底
硬保底:抽满 N 次必出指定稀有度
状态:已抽次数(当前未出稀有度的计数)
达到 N → 本次必然出传说/史诗
实现:
玩家级计数存储:gacha:{playerId}:{poolId}:pity
每次抽取:先判断是否触发保底
触发 → 强制稀有度,计数清零2.2 软保底
软保底:未出稀有度时概率随次数递增
基础概率 P0,每抽未出 +Δ
达到上限 Pmax 或硬保底 N 次必出
实现:
实际概率 = min(P0 + 未出次数 × Δ, Pmax)
概率递增逻辑见随机算法章节(概率递增/Pseudo Random Distribution)// 软保底示例:第 i 抽实际概率
double p = baseRate + pityCount * incrementRate;
p = Math.min(p, maxRate);2.3 计数管理
保底计数跨池/跨卡池策略:
同池累计(常见)
限时池结束 → 计数保留或折算(按运营规则)
计数与抽取同事务/同原子操作,防丢三、概率验证
3.1 服务端随机
抽卡必须服务端计算,客户端只是表现:
抽取流程:
1. 客户端请求抽卡(count=1/10)
2. 服务端校验货币/限次
3. 扣费 → 生成抽取结果(服务端随机)
4. 发奖(保底判断 → 结果生成 → 发放)
5. 写抽取记录,返回结果3.2 可复现随机
随机种子策略:
每次抽取记录 seed 与生成序号
用种子可复现同一结果(审计/客服举证)
种子来源:SecureRandom 等强随机
// 伪随机(可复现)+ 种子记录
Random random = new Random(seed);
for (int i = 0; i < count; i++) {
results.add(pickByRate(pool, random));
}审计验证:
记录每抽:seed、序号、结果、时间
运营后台可按玩家/时段重放校验
概率统计验证:大量抽取样本比对公示概率四、抽取记录与公示
4.1 记录存储
GachaLog:
logId、playerId、poolId、batchId
seed、count、results(Json:道具 + 品质)
costCurrency、costAmount
createTime
索引:(playerId, createTime)、(poolId, createTime)记录用途:
玩家查看历史("我的记录")
客服/审计举证
高价值道具全服公示4.2 公示与实时广播
公示策略:
传说级掉落 → 全服广播(带动氛围)
本服频道展示 + 昵称
公示可开关(按道具配置)
限时卡池:
公示概率 + 保底规则
卡池时间范围展示
结束前提醒五、实现要点
核心接口:
gacha(playerId, poolId, count)
getPity(playerId, poolId) // 保底进度查询
getLog(playerId, poolId, page) // 抽取记录
getPoolInfo(poolId) // 概率公示工程注意:
概率配置加载时校验总和
扣费与抽卡同事务(失败回滚)
保底计数 Redis + 落库双保险
抽取结果服务端生成,客户端不可影响常见坑:
并发抽卡超扣 → 同玩家串行 + 条件扣费
保底计数丢失 → 与抽取同原子写
概率与公示不符 → 配置校验 + 审计重放
客户端篡改结果 → 结果完全服务端生成与其他系统衔接:
消耗 → 货币系统
产出 → 道具系统(含碎片)
限时卡池 → 活动系统
全服公示 → 聊天系统频道消息