【问题标题】:Paused layer come unpause after start app from background从后台启动应用程序后,暂停的图层会取消暂停
【发布时间】:2017-03-23 17:24:03
【问题描述】:

我已将播放/暂停按钮设置为 gameLayer - 这里:How to prevent run SKAction on paused scene (after unpaused), texture of node not change after pause/unpause scene

一切正常,但我对后台应用程序无能为力。当我暂停 gameLayer 并且应用程序进入后台或锁定设备时,在应用程序进入前台后,游戏层会自动取消暂停。如何预防?

谢谢!

【问题讨论】:

  • 只需在您的场景中侦听 UIApplicationDidBecomeActiveNotification 并采取适当的操作(暂停 gameLayer)。如果您仍然卡住,请告诉我,我会为您写一个答案。
  • 我检查了苹果文档,发现只有static let UIApplicationDidBecomeActive: NSNotification.Name,但我不知道如何准确地使用它。例子会很棒!谢谢!

标签: ios swift sprite-kit


【解决方案1】:

所以这对我有用:

import SpriteKit
import GameplayKit

class GameScene: SKScene {

    var gameLayer = SKNode()

    override func didMove(to view: SKView) {
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(GameScene.pause),
                                               name: .UIApplicationDidBecomeActive,
                                               object: nil)
        let moveUp = SKAction.moveBy(x: 0, y: 100, duration: 2)
        let sequence = SKAction.sequence([moveUp, moveUp.reversed()])
        let loop = SKAction.repeatForever(sequence)

        let sprite = SKSpriteNode(color: .purple, size: CGSize(width: 100, height: 100))

        addChild(gameLayer)
        gameLayer.addChild(sprite)

        sprite.run(loop)
    }

    func pause(){

        gameLayer.speed = 0
    }

    override func willMove(from view: SKView) {
        super.willMove(from: view)

        NotificationCenter.default.removeObserver(self,
                                                  name: .UIApplicationDidBecomeActive,
                                                  object: nil)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        gameLayer.speed = gameLayer.speed == 0 ? 1 : 0
    }
}

我没有时间测试更多,但我期待这样的事情:

 func pause(){
        gameLayer.isPaused = true
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
       gameLayer.isPaused = !gameLayer.isPaused
    }

会起作用,但令人惊讶的是它不是(执行pause() 方法后节点继续移动)。我真的不知道这是一个错误还是一个功能:) 但恕我直言,我会说这是一个错误。无论如何,您可以使用 speed 属性实现您想要的。只需复制并粘贴此代码即可查看其工作原理。

【讨论】:

  • 也许像@Knight0fDragon 或@AlessandroOrnano 这样的人可能会帮助解释为什么isPaused 在这种情况下不起作用......也许我只是因为简短的测试而遗漏了一些东西,但似乎像一个错误。
  • 附注...因为UIApplicationDidBecomeActive 通知在应用程序一开始就被触发,gameLayer 将从一开始就暂停。所以你必须点击屏幕来取消暂停上下移动精灵的动作......
  • isPaused 行绝对有效我复制了您的代码,它按预期工作。奇怪的是,通知不会触发
  • @RonMyschuk 嗨,Ron,感谢您查看此内容。 isPausedtouchesBegan 中也适用于我。此外,通知会正确触发。但是,正如我所提到的,不知何故,在 pause() 方法中更改 isPaused 属性没有效果。您能否通过在pause() 方法中放置一个断点来确认当您从后台返回时它没有被执行?
  • 我已经尝试过了,但没有。我以前从未使用过这个特定的通知,过去我也很少使用过这些通知。也许我设置错了。我像您在代码中那样设置它,但是我需要在 AppDelegate 中这样做吗?我也很好奇这里发生了什么
【解决方案2】:

我做了一个可能不那么漂亮,但非常简单的解决方法。

刚刚在Scene类中添加var gamePaused = false,在pause()中设置为true,然后在

override func update(_ currentTime: TimeInterval) { 
    guard gamePaused == false else {
        if playLayer.isPaused == false {playLayer.isPaused = true}
        return
    }
.....
}

所以每次应用从后台启动时,playLayer.isPaused 设置为 true,只是在第一个渲染帧。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-30
    • 2018-08-01
    • 2015-10-30
    相关资源
    最近更新 更多