【问题标题】:My GameScene is returning nil when I try to use it in GameViewController当我尝试在 GameViewController 中使用它时,我的 GameScene 返回 nil
【发布时间】:2014-11-08 16:20:39
【问题描述】:

我正在使用 Swift 创建一个基本的宇宙飞船游戏,一切都运行良好,直到我尝试添加一个功能,即每次用户向上滑动时宇宙飞船都会向上移动。我添加了一个 UISwipeGestureRecognizer 并将它与我的 GameViewController 中的一个 IBAction 连接起来,然后我打算从中调用我的 GameScene 中的一个方法来使宇宙飞船向上移动。

import UIKit
import SpriteKit

extension SKNode {
    class func unarchiveFromFile(file : NSString) -> SKNode? {
        if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
            var sceneData = NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe, error: nil)!
            var archiver = NSKeyedUnarchiver(forReadingWithData: sceneData)

            archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
            let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as GameScene
            archiver.finishDecoding()
            return scene
        } else {
            return nil
        }
    }
}
class GameViewController: UIViewController {

    let scene: GameScene!

    @IBAction func swipeUp(sender: UISwipeGestureRecognizer){
        scene.movePlaneUp()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
            let skView = self.view as SKView
            skView.ignoresSiblingOrder = true
            scene.scaleMode = .AspectFill

            skView.presentScene(scene)
        }
    }

    override func shouldAutorotate() -> Bool {
        return false
    }

    override func supportedInterfaceOrientations() -> Int {
        if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
            return Int(UIInterfaceOrientationMask.AllButUpsideDown.rawValue)
        } else {
            return Int(UIInterfaceOrientationMask.All.rawValue)
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    override func prefersStatusBarHidden() -> Bool {
        return true
    }
}

一切都编译并且应用程序运行,但是,每当我尝试向上滑动时,我都会收到一个致命错误:在解开一行上的可选值时意外发现 nil

scene.movePlaneUp()

我知道发生错误是因为场景的值为 nil,但我该如何使该场景实际上具有 GameScene 的值?

这是我的 GameScene 代码:

import SpriteKit

class GameScene: SKScene {
    override func didMoveToView(view: SKView) {
        let bg = SKSpriteNode(imageNamed: "Background")
        bg.size = self.frame.size
        bg.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
        self.addChild(bg)
        let sprite = SKSpriteNode(imageNamed: "Spaceship")
        sprite.xScale = 0.6
        sprite.yScale = 0.5
        sprite.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMinY(self.frame)+CGRectGetMaxY(sprite.frame))
        sprite.name = "spaceship"
        self.addChild(sprite)
    }
    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        var t = touches.allObjects[0]
        let location = t.locationInNode(self)
        let action = SKAction.moveToX(location.x, duration:0.1)
        let n = self.childNodeWithName("spaceship")
        n?.runAction(action)
        let bullet = SKSpriteNode(imageNamed: "Spaceship")
        bullet.xScale = 0.05
        bullet.yScale = 0.05
        bullet.position = CGPoint(x: location.x, y: 200+bullet.position.y)
        bullet.runAction(SKAction.moveToY(1000, duration: 0.75))
        self.addChild(bullet)
    }
    func movePlaneUp(){
        let n = childNodeWithName("spaceship")
        n?.removeAllActions()
        let action = SKAction.moveBy(CGVector(dx: 0, dy: 100), duration: 1)
        n?.runAction(action)
    }
}

【问题讨论】:

    标签: ios swift fatal-error null optional


    【解决方案1】:

    我意识到我出现错误的原因是因为我从未为场景分配任何东西。我通过改变解决了我的问题

    let scene: GameScene!
    

    let myScene: GameScene!
    

    然后我将 viewDidLoad 更改为

    override func viewDidLoad() {
        super.viewDidLoad()
        if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
            let skView = self.view as SKView
            skView.ignoresSiblingOrder = true
            scene.scaleMode = .AspectFill
            skView.presentScene(scene)
            myScene = scene
        }
    }
    

    然后实际上为 myScene 分配了一个值

    【讨论】:

      【解决方案2】:

      我知道这有点晚了...如果您使用self.scene = scene 它也可以。这是由于scene var 使用if let scene 创建的,它覆盖了if let 范围内的任何其他同名变量。 ? 你现在可能已经知道了(因为它创建已经两年了):) 但是,我希望它对语言的新手有用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多