Design advanced games for Apple platforms
Graphics & Games 进阶 20m

为 Apple 平台设计高品质游戏体验

Design advanced games for Apple platforms

2024年6月10日

在 Apple 官方观看视频

一句话判断

统一游戏平台意味着你的游戏要同时适配 Mac、iPad、iPhone 三种形态——这篇 Session 给出了从首次启动到手柄适配的全套设计指南,核心原则是:让玩家零等待进入游戏,让 UI 适应设备而不是反过来。

这场 Session 讲了什么

Apple 在游戏领域的野心越来越清晰:统一游戏平台让同一款游戏可以跑在 Mac、iPad、iPhone 上。但这不意味着同一套 UI 能直接用——三种屏幕尺寸、三种交互方式、三种性能级别,每个维度都需要设计上的考量。

Session 从”首次启动体验”开始讲:玩家下载完一个 50GB 的游戏,结果打开还要再等一次下载,直接劝退。Apple 建议把前 15 分钟的游戏内容打包进 App Store 初始下载,后续章节用 On-Demand Resources 或 Background Assets 在后台加载。

然后是设备适配:默认设置应该自动检测硬件能力,而不是让玩家手动调分辨率和画质;UI 布局要用锚点分段而不是整体缩放;安全区域(Safe Area)的处理直接决定控件能不能点到。

下半部分由 Dylan 讲输入设计,核心是 Game Controller Framework 自动检测已配对手柄,减少玩家在设置界面里折腾的时间。

值得深挖的点

首次启动:15 分钟法则

“让玩家在安装完成后立刻开始玩”听起来简单,做起来需要从架构层面规划。Apple 建议初始下载包包含游戏的前 15 分钟内容,这个时间窗口足够让玩家进入心流。

后台下载用 On-Demand Resources(App Store 托管)或 Background Assets(自有服务器托管)。关键是要让这个过程对玩家完全透明——不要显示进度条,不要弹出”正在下载资源”的提示。如果玩家推进速度比下载速度快(这种情况在轻量级游戏中很常见),才在关卡选择界面等自然位置提示下载状态,同时允许玩家重玩已下载的关卡。

这个策略的 trade-off 是初始包体积会增大,但对用户体验的收益远大于多占的存储空间。一个值得参考的指标:玩家在首次启动后 3 分钟内的留存率,往往决定了一款游戏的生死。

UI 适配:锚点分段 vs 整体缩放

最直觉的适配方式是把整个 UI 等比缩放到目标屏幕上。但这么做的问题很多:iPhone 上控件可能太小够不到,iPad 上又太大显得空旷,Mac 上可能跟鼠标交互模式不匹配。

Apple 推荐的方案是把 UI 拆成独立区域,每个区域锚定到屏幕的某个边。比如左下角的方向键永远贴紧左下角,右上角的小地图永远贴紧右上角。屏幕尺寸变化时,各区域保持自己的物理尺寸和间距,中间的游戏画面自动填充剩余空间。

这跟 Web 的 Flexbox 布局思路异曲同工——不是让内容去适配容器,而是让容器去分配空间。配合 Safe Area 的处理(避开圆角、Home Indicator、Dynamic Island),可以确保每个平台的 UI 都在”安全且舒适”的位置。

代码片段

Game Controller Framework 自动检测手柄

// 自动检测已配对的手柄,不需要让玩家手动选择
NotificationCenter.default.addObserver(
    forName: .GCControllerDidConnect,
    queue: .main
) { notification in
    guard let controller = notification.object as? GCController else { return }
    // 读取手柄配置文件,映射按键到 UI
    let profile = controller.extendedGamepad
    profile?.buttonA.setValueChangedHandler { button, value, pressed in
        player.jump()
    }
}

场景:游戏启动时自动检测已连接的手柄并映射按键,玩家不需要进设置页手动配置。坑:手柄随时可能断开,要同时监听 .GCControllerDidDisconnect 通知。

On-Demand Resources 后台加载关卡

// 请求下载后续关卡资源
let request = NSBundleResourceRequest(tags: ["chapter2", "chapter3"])
request.loadingPriority = NSBundleResourceRequestLoadingPriorityBackground
try await request.beginAccessingResources()
// 资源可用后静默加载,不打断游戏

场景:玩家在第一章时后台下载第二章和第三章。坑:endAccessingResources() 会释放已下载的资源,确认不再需要之前不要调用。

Safe Area 适配 UI 锚点

// 用 GeometryReader 读取安全区域
GeometryReader { geometry in
    ZStack {
        GameView()
            .frame(maxWidth: .infinity, maxHeight: .infinity)

        // 左下角方向键,贴紧安全区域
        VStack {
            Spacer()
            HStack {
                DPadView()
                    .padding(.leading, geometry.safeAreaInsets.leading + 16)
                    .padding(.bottom, geometry.safeAreaInsets.bottom + 16)
                Spacer()
            }
        }
    }
}

场景:跨平台游戏的方向键布局,在 iPhone、iPad、Mac 上都贴紧左下角安全区域。坑:不同设备的 safeAreaInsets 值差异很大,在 Simulator 上测试所有目标机型。

最佳实践

已有项目迁移:如果你已经有一款跨平台游戏,先从”首次启动体验”开始优化——把初始关卡数据打包进主 Bundle,其他资源改为后台下载。UI 适配方面,先处理最严重的布局问题(控件被圆角遮挡、触控区域过小),再逐步迁移到锚点分段方案。

新项目起步:在架构设计阶段就规划好资源分块策略,把”前 15 分钟体验”作为硬约束。UI 布局从第一天就用锚点分段,不要先做一套”刚好够用”的布局再回头改。性能默认设置用设备型号自动匹配,给玩家一个”画质 vs 性能”的总开关就够了。

还有什么值得关注

  • Apple Design Resources 提供了各设备的 Safe Area 模板,可以直接在设计工具里使用。
  • Xcode Simulator 可以预览不同机型的边框、圆角和方向,建议在提交前过一遍全机型。
  • 移动端建议把设置粒度控制在”画质/性能”二选一,而不是提供十几个开关——玩家不想在手机上做调参这种事。
WWDC 2024