开始一个节点暂停的场景
Posted
技术标签:
【中文标题】开始一个节点暂停的场景【英文标题】:starting a scene with a node paused 【发布时间】:2017-01-09 16:35:18 【问题描述】:我正在开发一款基于 SpriteKit
和 Swift
的情侣的 ios 游戏。从 iOS 7.1 定位
我在游戏中实现短音效的方式是使用SKAction.playSoundFileNamed
方法运行动作,该方法在专门为此目的添加的普通层节点上执行:
let SoundsLayerNode = SKNode()
self.addChild(SoundsLayerNode)
SoundsLayerNode.runAction(soundXXX)
通过暂停整个节点 (SoundsLayerNode.paused = true
) 可以很容易地使 FX 声音静音,然后再次打开声音,取消暂停节点 (SoundsLayerNode.paused = false
)
当我尝试在节点暂停的情况下启动场景时出现问题。在 func didMoveToView
方法中我设置了 SoundsLayerNode.paused = true
但在第一个 Spritekit
循环开始后,节点会自动取消暂停
看来,SpriteKit
在 didmovetoview
完成后强制场景(自身)取消暂停,因此它的所有后代都取消暂停,从而触发了声音层节点上令人不快的副作用
你知道怎么解决吗?
谢谢
【问题讨论】:
尝试将此runAction (SKAction.runBlockself.SoundsLayerNode.paused = true)
添加到didMoveToView
恐怕它不起作用,因为问题发生在第一个渲染循环结束(或第二个循环开始)之后。如果我在 didMoveToView 中运行一个动作,它会在触发“取消暂停”效果之前的第一个 -didEvaluateAction 方法中执行
【参考方案1】:
一种解决方案是在节点上运行一个 SKAction 以在一定时间(例如 0.1 秒)后暂停它。
var pauseAction = SKAction.sequence([SKAction.wait(forDuration: 0.1), SKAction.pause()])
node.run(pauseAction)
您可以尝试使用 0.1,看看您可以将其设置到多低才能使其仍能正常工作。
如果这不起作用,你可以在你的 GameScene 中做一个这样的解决方法:
var pauseToggle = true
override func didFinishUpdate()
if(pauseToggle)
SoundsLayerNode.paused = true
pauseToggle = false
这是一种很垃圾的做法,但应该也可以。
【讨论】:
第二个选项仍然失败。我不知道为什么在第一个渲染循环中我不能暂停节点。似乎有必要跳过第二个循环。也许我可以尝试类似计数器的方法,并在计数器 ==2 时设置 SoundsLayerNode.paused = true。但是我不太喜欢这个选项 @Codediver 失败,因为节点中的仍然未暂停?是的,我同意即使使用布尔值也是一种令人讨厌的方式。也许在其他地方您正在取消暂停节点而不知道它。您的 GameScene 代码是否足够短,可以放入您的帖子中? MarshallD,您有机会阅读我的新帖子吗?我运行了一个简单的测试并检查了 testNode 在第一个循环结束时是否自动取消暂停。我有点困惑。【参考方案2】:代码很长,但我尝试了一个简单的 GameScene 测试,所以如果我运行该应用一段时间,您可以查看控制台中显示的结果:
在 didMoveToView 内部 testNode 已暂停:true 场景(自身)已暂停:false
循环更新:0 testNode 已暂停:true 场景(自身)已暂停:false
Loop_didEvaluateActions:0 testNode 已暂停:true 场景(自身)已暂停:false
Loop_didFinishUpdate: 0 testNode 已暂停:true 场景(自身)已暂停:false
循环更新:1 testNode 已暂停:假 场景(自身)已暂停:false
Loop_didEvaluateActions:1 testNode 已暂停:假 场景(自身)已暂停:false
Loop_didFinishUpdate: 1 testNode 已暂停:假 场景(自身)已暂停:false
spritekit 是否强制场景在第一次渲染循环后自行取消暂停?
//
// Test on paused Nodes
//
import SpriteKit
class GameScene: SKScene
let testNode = SKNode()
var loopCounter:Int = 0
override func didMoveToView(view: SKView)
self.addChild(testNode)
testNode.paused = true
print ("Inside didMoveToView")
print("testNode is paused:",testNode.paused)
print("scene(self) is paused:",scene!.paused)
print("")
override func update(currentTime: CFTimeInterval)
print ("Loop_Update:",loopCounter)
print("testNode is paused:",testNode.paused)
print("scene(self) is paused:",scene!.paused)
print("")
override func didEvaluateActions()
print ("Loop_didEvaluateActions:",loopCounter)
print("testNode is paused:",testNode.paused)
print("scene(self) is paused:",scene!.paused)
print("")
override func didFinishUpdate()
// This is the last chance to make changes to the scene
print ("Loop_didFinishUpdate:",loopCounter)
print("testNode is paused:",testNode.paused)
print("scene(self) is paused:",scene!.paused)
print("")
loopCounter=loopCounter+1
// After didFinishUpdate SKView renders the scene.
// Does spritekit force the scene to unpause itself here?
【讨论】:
根据您在此处所拥有的内容,您似乎是正确的,该节点最终不会暂停。如果在 didMoveToView 之后调用了一个方法,那么我不知道它。最好的解决方案是解决它 - 我有一个想法涉及一个 SKAction,它在大约 0.5 秒后被调用一次 - 你想让我把它添加到我的答案中吗? 是的,它确实发生在第一个渲染循环的末尾。我希望有人可以知道原因。请添加您的代码,这听起来很有趣,我想评价您的帮助 谢谢。您找到了问题的解决方案。您的代码给了我错误,但我根据您的解决方案重写了它: runAction (SKAction.sequence([SKAction.waitForDuration(0.1), SKAction.runBlockself.SoundsLayerNode.paused = true])) 在第一个 SKAction 中等待 0.1 秒已经足够短了,我认为每个渲染循环持续 0.0166 秒(60fps 时为 1/60 秒),所以 0.02 秒也应该足够短,0.1 可以正常工作: )以上是关于开始一个节点暂停的场景的主要内容,如果未能解决你的问题,请参考以下文章
Cassandra:将新节点引导到集群时,Long Par New GC 暂停