我一直在遵循Ray Wenderlich的旧教程:https://www.raywenderlich.com/1514-introduction-to-the-sprite-kit-scene-editor,遇到了问题。我已经多次遇到这个问题,甚至在stackoverflow网站上找到了一个“解决方案”:Passing Data Between Scenes (SpriteKit)
这是与教程相同的代码(进行了一些调整,与在Swift 2中编写的一样)。我觉得这是一个非常简单的解决方案,并且没有使用NSdefaults等代码。
这是对新场景的调用,请注意 soundToPlay 对象:
func gameOver(didWin: Bool) {
let menuScene = MenuScene(size: self.size)
menuScene.scaleMode = .aspectFill
menuScene.soundToPlay = didWin ? "fear_win.mp3" : "fear_lose.mp3"
let transition = SKTransition.flipVertical(withDuration: 1.0)
self.view?.presentScene(menuScene, transition: transition)
}
这就是我要呼叫的场景:
import SpriteKit
class MenuScene: SKScene {
var soundToPlay: String!
override func sceneDidLoad() {
self.backgroundColor = SKColor(red: 0, green:0, blue:0, alpha: 1)
// Setup label
let label = SKLabelNode(fontNamed: "AvenirNext-Bold")
label.text = "Press anywhere to play again!"
label.fontSize = 55
label.horizontalAlignmentMode = .center
label.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
addChild(label)
// Play sound
if let soundToPlay = soundToPlay {
run(SKAction.playSoundFileNamed(soundToPlay, waitForCompletion: false))
}
}
数据从不传递,并且对象的值为 nil
我怀疑它在Swift中已经发生了变化,因为本教程非常老,而在上一个 stackoverflow 问题中建议的“解决方案”也是如此。
如果是这样,那么现在实现这一目标的最佳方法是什么?
答案 0 :(得分:1)
声音的问题是您在调用sceneDidLoad之后设置了变量(在初始化期间发生),因此声音不会播放。
要解决此问题,请在您的didMove
方法中执行以下代码:
override func didMove(to view: SKView) {
guard let soundToPlay = soundToPlay else {fatalError("Unable to find soundToPlay")}
run(SKAction.playSoundFileNamed(soundToPlay, waitForCompletion: false))
}
在这里看不到崩溃的实际问题。
SKTransition
会在您使用SKLightNode
时出现问题,因此通过调用具有过渡效果的场景会使其崩溃。 SKTransition
一直被引入Metal所困扰,因此您唯一可以做的就是向Apple报告,并祈祷他们没有告诉您这是故意的。
到目前为止,请跟踪所有光源,并在过渡时将isEnabled
属性设置为false
。
您可能需要先创建场景的屏幕快照,然后再禁用光源以使其看起来不傻。
答案 1 :(得分:0)
您正在做的是,在重新加载场景(let menuScene = MenuScene(size: self.size)
)时,您将重置所有已定义的变量。
您可以使用UserDefaults:
func gameOver(didWin: Bool) {
let menuScene = MenuScene(size: self.size)
menuScene.scaleMode = .aspectFill
let soundToPlay = didWin ? "fear_win.mp3" : "fear_lose.mp3"
UserDefaults.standard.set(soundToPlay, forKey: "soundToPlay")
let transition = SKTransition.flipVertical(withDuration: 1.0)
self.view?.presentScene(menuScene, transition: transition)
}
并且:
import SpriteKit
class MenuScene: SKScene {
var soundToPlay: String!
override func sceneDidLoad() {
self.backgroundColor = SKColor(red: 0, green:0, blue:0, alpha: 1)
// Setup label
let label = SKLabelNode(fontNamed: "AvenirNext-Bold")
label.text = "Press anywhere to play again!"
label.fontSize = 55
label.horizontalAlignmentMode = .center
label.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
addChild(label)
// Play sound
if let soundToPlay = UserDefaults.standard.string(forKey: "soundToPlay") {
run(SKAction.playSoundFileNamed(soundToPlay, waitForCompletion: false))
}
}
然后,将其放入您的AppDelegate的applicationWillTerminate
函数中:
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
UserDefaults.standard.removeObject(forKey: "soundToPlay")
}
如果未将其放在AppDelegate中,则在完全关闭应用程序后,soundToPlay将保留。
我不知道UserDefaults
是否是实现此目标的最佳方法,但是在制作iOS
应用程序时我一直为此而苦恼,而我只是这样做了。因此,如果其他人有更好的答案,也请通知我!