让我在开始回答这个问题时先说我知道有人问过几次,但是最受好评的帖子here是在2014年,最热门的答案似乎不再起作用。
在我的游戏中,我所有的“移动”节点都作为pauseNode
的子节点。当按下暂停按钮或播放器离开应用程序时,将调用pauseScene()
:
func pauseScene() {
self.node.speed = 0
self.physicsWorld.speed = 0
self.node.isPaused = true
}
这将暂停所有精灵节点和发射器节点。如果应用程序从背景状态转换为前景状态,则可以使子画面节点保持暂停状态,但是粒子发射器似乎可以恢复动画。
我通过在应用程序启动一段时间后触发pauseScene()
解决了这个问题。
override func didMove(to view: SKView) {
NotificationCenter.default.addObserver(self, selector: #selector(GameScene.applicationDidBecomeActive(notification:)), name: NSNotification.Name.UIApplicationDidBecomeActive, object: app)
}
@objc func applicationDidBecomeActive(notification: NSNotification) {
NSDelay(0.01) {
pauseScene()
}
}
func NSDelay(_ delay:Double, closure:@escaping ()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}
虽然此解决方案可以暂停粒子,但是它并不是完美的,因为可以看到它们在瞬间移动以再次暂停它们(这是实际上重新暂停它们的最短延迟)。
因此,在阅读了我上面链接的文章之后,我尝试按照建议的方法在SKView子类中重写applicationDidBecomeActive()
,但无法调用该方法。如果可能的话,我想首先阻止这些粒子。谢谢
答案 0 :(得分:0)
所以,已经过去了一天多,我找到了一个更好的解决方案。 this帖子中的评论建议使用一个变量来记录场景的状态,并与暂停/播放功能一起对其进行更新:
var sceneIsPaused = false
func pauseScene() {
self.node.speed = 0
self.physicsWorld.speed = 0
self.node.isPaused = true
sceneIsPaused = true
}
func playScene() {
self.node.speed = 1
self.physicsWorld.speed = 1
self.node.isPaused = false
sceneIsPaused = false
}
然后,重写SKView的update
方法并检查该变量的状态。如果场景的应的暂停,暂停。这意味着如果场景自动取消暂停,它将重新暂停下一帧。这比设定的延迟更快和更清洁的:
override func update(_ currentTime: TimeInterval) {
if (sceneIsPaused == true) {
self.node.speed = 0
self.physicsWorld.speed = 0
self.node.isPaused = true
}
}