如何确保当前SKScene完全加载后再使用GamePad Controller操作?
解决tvOS中SKScene切换过快导致的交互失效问题
1. 基于SKScene生命周期的"就绪"判断
SKScene的didMove(to view:)方法是场景完全加载并添加到视图后的回调,作用和jQuery的$(document).ready()一致。你可以在游戏场景中添加标志位,仅当场景就绪后才响应手柄输入:
class GameScene: SKScene { private var isSceneReady = false override func didMove(to view: SKView) { super.didMove(to: view) // 执行游戏初始化操作(棋子创建、资源加载等) setupGamePieces() // 标记场景已就绪 isSceneReady = true } override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) { guard isSceneReady else { return } for press in presses { if press.type == .menu { // 切换场景前立即停止音效 stopAllSoundEffects() switchToMenuScene() } else if press.type == .select { // 处理棋子移动逻辑 moveGamePieces() } } } private func stopAllSoundEffects() { // 停止所有音效播放示例 self.removeAction(forKey: "backgroundMusic") // 若使用AVAudioPlayer,调用对应的player.stop()方法 } }
2. 全局控制输入可用性
在GameViewController中维护一个全局开关,切换场景时禁用输入,直到目标场景就绪后再启用:
class GameViewController: UIViewController { var canHandleInput = true func switchToScene(_ scene: SKScene) { // 切换场景前禁用输入 canHandleInput = false guard let skView = self.view as? SKView else { return } skView.presentScene(scene) } }
在游戏场景的didMove(to view:)中通知ViewController启用输入:
override func didMove(to view: SKView) { super.didMove(to: view) setupGamePieces() if let vc = view.window?.rootViewController as? GameViewController { vc.canHandleInput = true } }
手柄事件处理时先检查全局开关:
override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) { guard let vc = view.window?.rootViewController as? GameViewController, vc.canHandleInput else { return } // 后续按键逻辑处理... }
3. 场景切换时的音效强制停止
确保在触发场景切换的瞬间就停止所有音效,避免音效残留或干扰后续场景:
private func switchToMenuScene() { stopAllSoundEffects() let menuScene = MenuScene(size: self.size) if let vc = view.window?.rootViewController as? GameViewController { vc.switchToScene(menuScene) } }
内容的提问来源于stack exchange,提问作者user22530416
相关产品推荐
相关产品推荐

