Graphics & Games 进阶 20m
游戏手柄的新进展
Advancements in Game Controllers
2020年6月24日
一句话判断
Xbox 和 PS4 手柄终于可以在 Apple 设备上用了——这场 Session 讲解了如何在你的游戏或 App 中正确适配这些手柄的全部功能。
这场 Session 讲了什么
这场 Session 介绍了 iOS、iPadOS、macOS 和 tvOS 对游戏手柄支持的重大更新。2020 年 Apple 正式支持了 Xbox One 和 PlayStation DualShock 4 手柄,这标志着 Apple 平台的游戏体验从纯触摸屏向核心游戏场景迈出了重要一步。
演讲者首先介绍了 GameController 框架的更新。GCController 现在可以识别三种类型的手柄:Extended Gamepad(标准布局,有双摇杆和肩键)、Micro Gamepad(Siri Remote 等)和新的 DualSense/DualShock 4 特定 profile。每种手柄都有对应的按钮、摇杆和触控板的映射。
Session 的核心部分详细讲解了如何适配不同手柄的特殊功能:Xbox 手柄的扳机键震动(Haptic Feedback)、PS4 手柄的触控板和 Light Bar、以及两者的陀螺仪和加速度计数据。演讲者还讨论了如何处理手柄的连接/断开事件、如何为手柄输入做按键映射自定义,以及如何同时支持触摸屏和手柄两套输入方式。
最后,演讲者展示了一些最佳实践,确保游戏在手柄和触摸屏之间无缝切换。
值得深挖的点
- Haptic Feedback 的差异化:Xbox 手柄使用 Impulse Trigger(扳机键内嵌震动马达),可以实现”扣动扳机时感觉阻力”的效果。PS4 手柄的震动是传统的双马达。不同手柄的触觉反馈能力差异很大,你的游戏需要根据手柄类型提供适配的反馈方案。
- 手柄输入的”触摸降级”设计:不是所有用户都有手柄。你的游戏必须同时支持触摸输入,而且在设计上要确保触摸操作不会因为”顺手柄设计”而变得别扭。Apple 建议把触摸和手柄视为两套独立的交互设计,而非同一套设计的手柄适配。
代码片段
// 监听游戏手柄连接
import GameController
NotificationCenter.default.addObserver(
self, selector: #selector(controllerConnected),
name: .GCControllerDidConnect, object: nil
)
NotificationCenter.default.addObserver(
self, selector: #selector(controllerDisconnected),
name: .GCControllerDidDisconnect, object: nil
)
@objc func controllerConnected(_ notification: Notification) {
guard let controller = notification.object as? GCController else { return }
print("手柄已连接: \(controller.vendorName ?? "未知")")
// 检测手柄类型
if controller.extendedGamepad != nil {
setupExtendedGamepad(controller.extendedGamepad!)
}
}
// 读取手柄输入
func setupExtendedGamepad(_ gamepad: GCExtendedGamepad) {
// 摇杆输入(左摇杆控制移动)
gamepad.leftThumbstick.valueChangedHandler = { _, xValue, yValue in
self.player.move(x: CGFloat(xValue), y: CGFloat(yValue))
}
// 按钮输入
gamepad.buttonA.pressedChangedHandler = { _, _, isPressed in
if isPressed {
self.player.jump()
}
}
// 扳机键(用于精细控制)
gamepad.rightTrigger.valueChangedHandler = { _, value, isPressed in
self.player.shoot(intensity: CGFloat(value))
}
// Xbox 手柄震动反馈
if let haptic = gamepad.controller?.hapticEngines?.first {
haptic.start()
// 在特定事件触发震动
}
}
// 处理 PS4 手柄的触控板
if let dualShock = controller.extendedGamepad as? GCDualShockGamepad {
dualShock.touchpadPrimary.valueChangedHandler = {
_, xValue, yValue in
// 触控板坐标范围 [0, 1]
let touchX = CGFloat(xValue)
let touchY = CGFloat(yValue)
self.handleTouchpadInput(x: touchX, y: touchY)
}
// 使用 Light Bar 提供状态信息
dualShock.setLightColor(.red) // 红色 = 危险
dualShock.setLightColor(.green) // 绿色 = 安全
}
最佳实践
- 游戏启动时检测手柄状态,有手柄自动切换到手柄控制模式
- 为所有手柄操作提供触摸屏替代方案,确保无手柄也能完整游戏
- 利用扳机键的模拟值做精细控制(如油门力度),而非简单的开关
- 手柄断开时自动暂停游戏,给用户重新连接的时间
- 测试时覆盖 Xbox、PS4 和 MFi 三种手柄,确保兼容性
还有什么值得关注
- PS5 的 DualSense 手柄后来也在 iOS 15 中获得了支持,包括自适应扳机
- 搭配 “Bring keyboard and mouse gaming to iPad” 一起看,可以了解 iPad 上完整的输入方案
- tvOS 上手柄是主要输入方式,如果你的游戏要上 Apple TV,手柄适配是必须的
WWDC 2020