WWDC Quick Look 💓 By SwiftGGTeam
Get started with Game Center

Get started with Game Center

观看原视频

Highlight

Xcode 26 新增 .gamekit bundle,把 Leaderboards、Challenges、Activities、Achievements 的配置从 App Store Connect 网页迁回项目源码,可纳入版本控制和 Code Review,并通过 Game Progress Manager 在本地直接调试分数提交与深链跳转。


核心内容

过去做 Game Center 集成的开发者都遇到过一个反复出现的痛点:所有的 Leaderboard、Achievement、Challenge 配置都散落在 App Store Connect 网页上,改一个 ID 要登录浏览器,多人协作没有 diff,回滚靠记忆,连本地跑测试都要打真实数据到服务器。一个简单的”测一下新加的关卡分数能不能正确上报”,往往要先在 ASC 建条目、提交真实分数、刷新榜单、再手动清理脏数据。

WWDC25 的第一刀就砍在这里。Xcode 26 新增了 .gamekit bundle —— 一个本地文件,里面声明你所有的 Game Center 资源。它可以从 App Store Connect “Pull”下来,编辑完再”Push”回去;同时本地配备 Game Progress Manager,所有调试的分数都只活在这次会话里,不会污染线上数据。这意味着 Game Center 的配置从此变成代码资产,可以走 PR、走 Code Review、跟着分支走。

今年另两个主菜是 Challenges 和 Activities。Challenges 直接长在已有的 Leaderboard 之上 —— 如果你已经在用 submitScore(),理论上不写一行代码就能让玩家发起带时限的好友对战;Activities 则是深链入口,把好友点进来的玩家直接送到正确的关卡或多人房间,并通过 Game Center 自动生成的 Party Code 把人聚到同一个对局里。


详细内容

Game Center 的初始化只有两步:加 entitlement,调一次 GameKit。下面这段 Swift 是官方推荐的最早初始化时机(04:17):

GKLocalPlayer.local.authenticateHandler = { _, error in
    print("\(GKLocalPlayer.local.alias) is ready to play!")
}

关键点:

  • GKLocalPlayer.local 是单例,代表本机当前登录的 Game Center 玩家。
  • authenticateHandler 是一个回调,赋值后 GameKit 才真正开始走鉴权流程。
  • handler 触发后,GKLocalPlayer.local.alias 才是有效值;之前读到的是空字符串。
  • 官方建议把这段挂在 title screen 出现时执行,越早调用,越早进入”Top Played Games”曝光池。

Unity 开发者用同样的语义,写法是 C#(04:29):

var player = await GKLocalPlayer.Authenticate();
Debug.Log($"{player.alias} is ready to play!");

Unity Plugin 从 GitHub 仓库(apple/unityplugins)拉源码自己 build,build 完会生成一个已经带好 entitlement 的 Xcode 工程。

到了 Challenges,这是这次设计上最克制的地方 —— 它不要求你新增 API。你提交分数的那行代码不变(13:07):

GKLeaderboard.submitScore(points,
         context: 0,
         player: GKLocalPlayer.local,
         leaderboardIDs: ["thecoast.lb.capecod"])

关键点:

  • leaderboardIDs 是数组,意味着一次提交可以打到多个榜单。
  • 同一个 API 会自动把分数同步给所有关联到该榜单的进行中 Challenge,不需要单独调一个 submitChallengeScore
  • 官方反复强调:每次关卡结束后只提交一次分数,不要累加 lifetime 分数 —— Challenge 是技巧比拼,不是肝度比拼。
  • context 是给开发者自由发挥的整数字段,可以塞关卡 ID、武器配置等额外维度。

Activities 把深链拉到了系统层。下面这段是把好友点进来的玩家送回正确关卡的入口(20:24):

extension AppDelegate: GKLocalPlayerListener {

    func player(_ player: GKPlayer, wantsToPlay activity: GKGameActivity) async -> Bool {
        let activityId = activity.activityDefinition.identifier

        if activityId == "thecoast.activity" {
            let level = activity.properties["level"]

            if level == "capecod" {
                startCapeCod(activity)
            }
        }

        return true
    }

}

关键点:

  • GKLocalPlayerListener 是协议,注册之后 GameKit 把所有外部唤起都丢到这个 handler。
  • activity.activityDefinition.identifier 是你在 Xcode .gamekit bundle 里手填的字符串,要和资源端对齐。
  • activity.properties 是字典,承载在 Xcode 里设置的 base properties + 关联资源(如 leaderboard)的 properties 合并结果。
  • handler 返回 Bool 告诉系统是否成功接管这次跳转 —— 返回 false 时系统会做兜底。

如果做多人游戏,Activity 自带 Party Code 机制(22:35),可以把同一个 Code 的玩家凑成一桌:

extension AppDelegate: GKLocalPlayerListener {
    func player(_ player: GKPlayer, wantsToPlay activity: GKGameActivity) async -> Bool {
        let activityId = activity.activityDefinition.identifier

        if activityId == "thecoast.multiplayer" {
            startMultiplayer(partyCode: activity.partyCode)
        }
        return true
    }
}

关键点:

  • activity.partyCode 由 Game Center 自动生成,无需自建房间号系统。
  • iMessage 分享 Activity 时,Code 会被嵌进 OpenGraph 网页,对端即使没装 Games app 也能看到分享卡片。
  • UI 上必须显示当前 Party Code 并提供手动输入入口,因为玩家可能从另一台设备/平台收到 Code。

如果你不想自建房间匹配,也可以一行接入 Game Center 现成的 matchmaking(22:48):

let match = try await activity.findMatch()

调试流程也是这次的亮点。Scheme → Run Options 里勾选 “GameKit Configuration Debug Mode”,启动游戏后 Debug 菜单里打开 Game Progress Manager,所有 .gamekit bundle 里的资源都列在面板上。你可以以任意玩家身份提交任意分数,Activity 的深链可以直接在 Xcode 里点击触发,效果等同于真机点击。所有调试数据只活在本次会话里,不会写到服务器(24:03)。


核心启发

  • 做什么:把现有项目里的 Game Center 配置从 App Store Connect 迁回 .gamekit bundle。

    • 为什么值得做:配置和代码一起进 Git,PR 里能看到 diff,回滚不再靠记忆,多人协作不会互相覆盖。
    • 怎么开始:Xcode 26 → New File → “GameKit Bundle” → 在 ellipsis 菜单选 “Pull from App Store Connect”,选好 team 和游戏,资源会原样落地到本地文件。
  • 做什么:给已有的 Leaderboard 加 Challenge,零代码获得”好友约战”功能。

    • 为什么值得做:复用现有 submitScore 调用路径,零侵入;Challenge 自带时限和好友邀请 UI,把单机榜单瞬间变社交对局。
    • 怎么开始:在 .gamekit bundle 里给目标 Leaderboard 添加一个 Challenge 条目,配置图、displayName、允许时长(1 天/3 天/1 周),确认 submitScore()leaderboardIDs 写对即可。
  • 做什么:为常用关卡或多人房间配 Activity 深链。

    • 为什么值得做:好友从 Games app 或 iMessage 点进来直接到关卡现场,跳过开屏、菜单、章节选择这些摩擦层,转化率显著高于”打开游戏让用户自己找”。
    • 怎么开始:在 .gamekit bundle 新建 Activity,关联对应 Leaderboard 并填 properties(如 level: "capecod");实现 GKLocalPlayerListener.player(_:wantsToPlay:),根据 identifierproperties 做路由。
  • 做什么:把 Game Progress Manager 写进开发流程,替代真实服务器调试。

    • 为什么值得做:调试期间不写脏数据到线上榜单;深链可以直接在 Xcode 里点;可以用任意玩家身份模拟提交,方便测多人交互场景。
    • 怎么开始:编辑 Scheme → Run Options,勾上 GameKit Configuration Debug Mode;启动后从 Debug 菜单开 Game Progress Manager,选当前设备和你的游戏。

关联 Session

评论

GitHub Issues · utterances