Graphics & Games 进阶 25m
接入 Game Center:排行榜、成就和多人游戏
Tap into Game Center: Leaderboards, Achievements, and Multiplayer
2020年6月25日
一句话判断
排行榜、成就和多人匹配——Game Center 提供了完整的社交游戏基础设施,你不需要自己搭建后端就能拥有这些能力。
这场 Session 讲了什么
这场 Session 是 Game Center 系列的第二部分,聚焦于三个核心游戏功能的 API 使用:Leaderboards(排行榜)、Achievements(成就)和 Multiplayer(多人游戏)。与第一部分(Dashboard UI)不同,这场更偏重后端 API 的使用方式。
排行榜部分介绍了新的 GKLeaderboard API。你可以按时间范围(今天、本周、所有时间)查询排名,也可以按社交范围(全局、仅好友)过滤。2020 年的更新增加了对 “Recurring Leaderboards” 的支持——你可以设置每周或每月自动重置的排行榜,鼓励玩家持续参与。
成就部分讲解了 GKAchievement 的提交和追踪。每个成就有一个唯一 ID、一个完成百分比(0-100%)和一个显示状态(是否已向好友展示)。你可以为成就设置隐藏状态——玩家在达成之前看不到具体要求,这增加了探索乐趣。
多人游戏部分是最重要的更新。Apple 引入了基于邀请的实时多人匹配(Real-Time Multiplayer)的改进,以及新的 Turn-Based Multiplayer API。Session 重点讲解了如何处理匹配流程、玩家状态同步、以及断线重连。
值得深挖的点
- Recurring Leaderboard 的设计价值:传统的全局排行榜有一个致命问题——新玩家永远追不上老玩家的高分,逐渐失去参与动力。Recurring Leaderboard 通过定期重置解决了这个问题。每周重置的排行榜让所有玩家每周都有争夺第一名的机会。
- Turn-Based Multiplayer 的使用场景:回合制多人游戏不需要所有玩家同时在线。Apple 的 Game Center 提供了完整的回合管理:推送通知提醒轮到谁了、处理玩家退出、自动判定超时。这比自建回合系统简单得多。
代码片段
// 加载排行榜数据
func loadLeaderboard() {
GKLeaderboard.loadLeaderboards(IDs: ["weekly_score"]) { leaderboards, error in
guard let leaderboard = leaderboards?.first else { return }
// 加载全球前 10 名
leaderboard.loadEntries(
for: .global,
timeScope: .week,
range: NSRange(1...10)
) { entries, totalPlayers, error in
for entry in entries ?? [] {
print("\(entry.player.alias): \(entry.score)")
}
}
// 加载好友排名
leaderboard.loadEntries(
for: .friendsOnly,
timeScope: .week,
range: NSRange(1...25)
) { entries, _, _ in
self.displayFriendScores(entries)
}
}
}
// 提交成就进度
func unlockAchievement(id: String, percent: Double = 100.0) {
let achievement = GKAchievement(identifier: id)
achievement.percentComplete = percent
achievement.showsCompletionBanner = true // 完成时显示横幅
GKAchievement.report([achievement]) { error in
if let error = error {
print("成就提交失败: \(error)")
}
}
}
// 渐进式成就(如"收集 50 个金币")
func onCoinCollected(total: Int) {
let percent = min(Double(total) / 50.0 * 100.0, 100.0)
unlockAchievement(id: "collect_50_coins", percent: percent)
}
// 实时多人匹配
func startMultiplayerMatch() {
let request = GKMatchRequest()
request.minPlayers = 2
request.maxPlayers = 4
request.inviteMessage = "来一起玩吧!"
let matchmaker = GKMatchmakerViewController(matchRequest: request)
matchmaker?.matchmakerDelegate = self
present(matchmaker!, animated: true)
}
// 匹配成功后处理
func matchmaker(
_ viewController: GKMatchmakerViewController,
didFind match: GKMatch
) {
match.delegate = self
viewController.dismiss(animated: true)
// 通过 match.sendData 发送游戏数据
let gameData = encodeGameState()
try? match.sendData(
gameData,
to: match.players,
dataMode: .reliable
)
}
最佳实践
- 排行榜分数提交不要太频繁,在合适的时机(如关卡结束时)批量提交
- 成就设计要有梯度:简单成就给新手成就感,困难成就给核心玩家挑战
- 多人匹配时提供 AI 填充选项,匹配不到真人时用 AI 替代
- 处理断线重连逻辑,网络不稳定时不要让玩家直接丢失进度
- 测试时使用沙盒账号验证排行榜和成就的正确性
还有什么值得关注
- Game Center 的服务端 API 允许你在自己的服务器上验证分数和成就的合法性
- “Tap into Game Center: Dashboard, Access Point, and Profile” 是这个系列的第一部分,介绍 UI 集成
- 如果你在做跨平台多人游戏,需要考虑 Game Center 玩家与其他平台玩家的互通问题
WWDC 2020