WWDC Quick Look 💓 By SwiftGGTeam
Design advanced games for Apple platforms

Design advanced games for Apple platforms

观看原视频

Highlight

Apple 统一游戏平台让同一款游戏可以跑在 Mac、iPad、iPhone 上,但三种屏幕尺寸、三种交互方式和三种性能级别要求游戏在每个维度都做针对性设计。


核心内容

玩家下载完一个 50GB 的大作,满心期待地点开图标,结果弹出一行字:“请等待额外内容下载”。Apple 的设计师 Linda 直说:这在 Apple 平台上是扣分项。Apple 用户习惯的是”装完就能用”,任何让玩家在启动后继续等待的体验都会拉低第一印象。

她的解决方案很具体:把前 15 分钟的游戏内容打包进 App Store 初始下载包,后续章节用 On-Demand Resources(托管在 App Store)或 Background Assets(托管在开发者自己的服务器)在后台静默加载。玩家感知到的是”装完即玩”,而不是”装完再等”。

但安装体验只是第一步。同一款游戏要在 Mac、iPad、iPhone 上都跑得好,还要面对三个设计维度:默认设置该自动检测硬件能力还是让玩家手动调?UI 布局该整体缩放还是按锚点分段?安全区域内的控件能不能被点到?Linda 和 Dylan 在下半场逐一拆解了这些问题。Dylan 关于触控设计的部分尤其关键——触控屏的输入面同时就是输出面,设计输入本身就是设计 UI。

详细内容

首次启动:把等待藏起来

Apple 建议初始下载包含前 15 分钟可玩内容(02:28)。后台加载使用两种框架:

  • On-Demand Resources:资源托管在 App Store,适合不太频繁更新的内容
  • Background Assets:资源托管在开发者自己的服务器,适合需要频繁更新的内容

如果玩家推进速度超过了加载速度,才在 UI 中提示下载进度——最好放在关卡选择界面等不干扰游戏的地方,同时允许玩家重玩已下载的关卡(03:07)。

默认设置:自动检测代替手动选择

设备型号、屏幕分辨率、已配对的外设——这些信息系统都能直接拿到,不需要玩家填写(04:17)。对于手柄,Game Controller Framework 可以自动检测已配对手柄并获取其 profile,直接映射到 UI 上(04:57)。

性能默认值也应该按设备能力自动设置:Mac 上画质开高一些,iPhone 上偏重性能。移动端可以把一堆细粒度选项压缩成一个”画质 vs 性能”的总开关(05:44)。

UI 布局:锚点分段,不要整体缩放

最简单的适配方式是整体缩放 UI,但 Linda 明确不推荐:缩放会导致控件位置不精确,触控区域可能过大或过小,看起来也不对齐(06:48)。正确做法是把 UI 拆成多个区段,每个区段锚定到屏幕的某一边。在不同设备上,每个区段保持一致的尺寸和到锚点的距离(07:08)。

安全区域与全屏设计

Safe Area 是 Apple 设备上放置 UI 的安全范围(08:00):

  • iPad/iPhone:避免圆角遮挡、Home Indicator、Dynamic Island
  • Mac:顶部留出圆角和摄像头区域

Apple Design Resources 提供了 Safe Area 模板,Xcode Simulator 可以预览不同设备的边框和方向。但 Safe Area 只是 UI 定位的参考,游戏画面本身应该占满全屏(09:18)。

如果游戏内容被设备比例裁切,优先调整摄像机焦距和角度;如果是预渲染过场动画,才用 letterboxing,并用黑色或自定义美术素材填充黑边区域(09:55)。

文字与控件尺寸

从大屏 TV 搬到小屏设备时,文字和控件尺寸是最容易被忽略的问题(10:25):

平台默认文字大小最小文字大小默认触控区域最小触控区域
iPhone/iPad17pt11pt44×44pt28pt
Mac13pt10pt28×28pt20pt

如果控件太多放不下,用 ScrollView 而不是缩小字号(12:58)。

手柄图标与键鼠适配

Apple 平台支持的手柄种类比大多数平台更广,每种手柄的按键图标(glyph)不同。不要把图标硬编码到游戏素材里,应该用 GameController framework 获取当前手柄对应的正确图标(15:02)。SF Symbols app 提供了完整的图标库。键盘方面,Apple 键盘的修饰键排列顺序与 PC 键盘不同,需要验证并调整快捷键映射(15:27)。

使用 GameController framework 检测手柄并获取图标的代码如下:

import GameController

// 监听手柄连接通知
NotificationCenter.default.addObserver(
    forName: .GCControllerDidConnect,
    object: nil, queue: .main
) { notification in
    guard let controller = notification.object as? GCController else { return }

    // 获取手柄的物理输入 profile
    if let gamepad = controller.extendedGamepad {
        // 根据手柄类型获取正确的按键图标
        let buttonAGlyph = gamepad.buttonA.sfSymbolName
        let buttonBGlyph = gamepad.buttonB.sfSymbolName
        let leftTriggerGlyph = gamepad.leftTrigger.sfSymbolName

        // 用获取到的 glyph 名称更新 UI
        updateButtonIcons(a: buttonAGlyph, b: buttonBGlyph, lt: leftTriggerGlyph)
    }
}

// 启动手柄发现
GCController.startWirelessControllerDiscovery {}

关键点:

  • GCControllerDidConnect 通知在手柄配对时触发,无需让玩家手动配置
  • controller.extendedGamepad 提供了完整的手柄输入 profile,包括所有按钮和摇杆
  • sfSymbolName 属性返回当前手柄对应的 SF Symbols 图标名称,确保 Xbox、PlayStation 等不同手柄显示各自的正确图标
  • startWirelessControllerDiscovery 启动蓝牙手柄搜索,配合通知使用实现自动检测

触控输入设计(Dylan 部分)

Dylan 的核心观点:触控屏的输入面就是输出面,设计输入就是设计 UI(16:22)。

移动与镜头:用虚拟摇杆替代左拇指杆,但不用的时候要隐藏;右拇指杆不要用虚拟摇杆,改用直接触控拖拽来控制镜头——速度和精度更接近鼠标而不是摇杆(18:06)。虚拟摇杆的输入区域要尽可能大,因为玩家无法像物理摇杆那样靠触觉定位(17:19)。冲刺功能可以直接集成到虚拟摇杆中——推到最远触发,不需要额外按钮(17:58)。

控件放置:避开安全区域、避开移动/镜头输入区域、避开角色位置。剩余空间中,拇指附近放高频操作,屏幕顶部放低频操作如菜单按钮(19:37)。需要注意左右手同时操作的搭配:L2 瞄准 + R2 射击在手柄上很自然,但在触控上会导致无法同时移动和瞄准——应该把瞄准放到右手侧(20:10)。

动态行为:用描述性的图标替代手柄按钮图标;当操作在当前上下文不可用时直接移除控件而不是灰化;在控件上反映游戏状态(比如技能冷却)(20:46)。

反馈:触控没有物理反馈,所以每个按钮必须有按压状态(22:07)。在忙碌的游戏场景中,视觉反馈要延伸到控件边界之外(比如光晕效果),因为手指可能遮挡按钮本身。配合声音和触觉反馈(haptics)增强响应感(22:37)。

核心启发

  • 做什么:实现”前 15 分钟即玩”的安装策略。为什么值得做:Apple 用户对”装完即用”有强烈预期,启动后还要等待会直接劝退。怎么开始:将初始关卡数据打包进主 Bundle,后续章节改为 On-Demand Resources 或 Background Assets 后台加载;仅在玩家推进到未加载区域时才显示下载进度。

  • 做什么:用锚点分段替代整体缩放来适配多屏幕。为什么值得做:整体缩放会导致控件位置偏移、触控区域不合理,在不同设备上看起来不对齐。怎么开始:把 UI 拆成多个区段,每个区段锚定到屏幕某一边,保持一致的尺寸和到锚点的距离;用 Xcode Simulator 在不同设备上验证布局。

  • 做什么:为触控设计专属输入方案,而不是照搬手柄映射。为什么值得做:触控屏的输入面即输出面,照搬手柄方案会导致控件遮挡画面、操作不便。怎么开始:移动用可隐藏的大区域虚拟摇杆(冲刺集成到摇杆最远端),镜头用直接拖拽而非虚拟摇杆;根据上下文动态显示/隐藏控件;每个触控按钮添加按压状态 + 光晕反馈 + haptics。

  • 做什么:自动检测硬件能力并设置默认画质。为什么值得做:玩家不应该手动选择屏幕分辨率和画面等级——这些信息设备自己知道。怎么开始:读取设备型号和屏幕分辨率自动设定性能档位;移动端将细粒度选项压缩为一个”画质 vs 性能”总开关;用 Game Controller Framework 自动检测手柄并映射按键。

关联 Session

评论

GitHub Issues · utterances