Ios SpriteKit:在展开时意外发现零,可以';t实现多个菜单场景

Ios SpriteKit:在展开时意外发现零,可以';t实现多个菜单场景,ios,swift,sprite-kit,Ios,Swift,Sprite Kit,我试图呈现一个包含两个按钮的菜单作为初始场景:播放,积分。单击“播放”时,我想用4个按钮呈现另一个菜单场景:tutorial、easy、hard、back 该策略只是将按钮创建为SKSpriteNode对象,并在touchsbegind功能中处理点击 在我的menuScene.sks文件中,我正确地放置并命名了我的节点。在这里,您可以查看链接到此场景的menuScene.swift文件: import SpriteKit class menuScene: SKScene { var play

我试图呈现一个包含两个按钮的菜单作为初始场景:
播放
积分
。单击“播放”时,我想用4个按钮呈现另一个菜单场景:
tutorial
easy
hard
back

该策略只是将按钮创建为
SKSpriteNode
对象,并在
touchsbegind
功能中处理点击

在我的
menuScene.sks
文件中,我正确地放置并命名了我的节点。在这里,您可以查看链接到此场景的
menuScene.swift
文件:

import SpriteKit

class menuScene: SKScene {

var playButton:SKSpriteNode!
var creditsButton:SKSpriteNode!

override func didMove(to view: SKView) {
    playButton = self.childNode(withName: "playButton") as! SKSpriteNode
    creditsButton = self.childNode(withName: "creditsButton") as! SKSpriteNode
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    // transition is defined in Helper.swift
    let touch = touches.first

    if let location = touch?.location(in: self){

        let nodesArray = self.nodes(at: location)

        if nodesArray.first?.name == "playButton" {
            let nextScene = difScene(size: self.size)
            self.view?.presentScene(nextScene, transition: transition)
        } else if nodesArray.first?.name == "creditsButton" {
            let nextScene = creditsScene(size: self.size)
            self.view?.presentScene(nextScene, transition: transition)
        }
    }
  }
}
如果可能有用,这是我的
GameViewController.swift

import SpriteKit

class difScene: SKScene {

var tutButton:SKSpriteNode!
var easyButton:SKSpriteNode!
var hardButton:SKSpriteNode!
var backButton:SKSpriteNode!

override func didMove(to view: SKView) {
    tutButton = self.childNode(withName: "tutButton") as! SKSpriteNode // error
    easyButton = self.childNode(withName: "easyButton") as! SKSpriteNode
    hardButton = self.childNode(withName: "hardButton") as! SKSpriteNode
    backButton = self.childNode(withName: "backButton") as! SKSpriteNode
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let transition = SKTransition.push(with: .down, duration: 0.2)
    let touch = touches.first

    if let location = touch?.location(in: self){

        let nodesArray = self.nodes(at: location)
        if nodesArray.first?.name == "tutButton" {

            let nextScene = GameScene(size: self.size)
            self.view?.presentScene(nextScene, transition: transition)
        }

        if nodesArray.first?.name == "easyButton" {
            let nextScene = difScene(size: self.size)
            self.view?.presentScene(nextScene, transition: transition)
        }

        if nodesArray.first?.name == "hardButton" {
            let nextScene = difScene(size: self.size)
            self.view?.presentScene(nextScene, transition: transition)
        }

        if nodesArray.first?.name == "backButton" {
            let nextScene = menuScene(size: self.size)
            self.view?.presentScene(nextScene, transition: transition)
        }
    }
  }
}
import UIKit
import SpriteKit
import GameplayKit

class GameViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    if let scene = GKScene(fileNamed: "menuScene") {

        // Get the SKScene from the loaded GKScene
        if let sceneNode = scene.rootNode as! menuScene? {

            // Set the scale mode to scale to fit the window
            sceneNode.scaleMode = .aspectFill

            // Present the scene
            if let view = self.view as! SKView? {
                view.presentScene(sceneNode)

                view.ignoresSiblingOrder = true

                view.showsFPS = false
                view.showsNodeCount = false
            }
        }
    }
}

override var shouldAutorotate: Bool {
    return true
}

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    if UIDevice.current.userInterfaceIdiom == .phone {
        return .allButUpsideDown
    } else {
        return .all
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Release any cached data, images, etc that aren't in use.
}

override var prefersStatusBarHidden: Bool {
    return true
  }
}
我得到的错误是:

线程1:致命错误:在展开可选值时意外发现nil


我知道这不是唯一的错误。我用谷歌搜索,看了教程,并试图从其他StackOverflow线程中获得解决方案,但未能克服这一点

错误在这一行

tutButton = self.childNode(withName: "tutButton") as! SKSpriteNode // error
因为没有名为“tutButton”的子节点,所以强制将其强制转换为
SKSpriteNode
会导致错误

当按下播放按钮时,您调用此代码:

let nextScene = difScene(size: self.size)
self.view?.presentScene(nextScene, transition: transition)
这将初始化一个新的
difScene
,并显示它,它反过来调用上面正在崩溃的代码行

您是否有相应的
sks
文件用于添加在
didMove
中引用的四个按钮的
difScene

如果是这样,您需要像在菜单场景中一样,使用
sks
文件初始化
difScene

let scene = GKScene(fileNamed: "difScene")
如果没有,则需要创建这四个按钮节点,并以编程方式将它们作为子节点添加到场景中



旁注:在Swift中,惯例是以大写字母开头命名类型。你的
menuScene
应该是
menuScene
,你的
difScene
应该是
difScene
。这将使其他人更容易阅读和理解您的代码。

很抱歉,这是我Java时代的习惯。。。我有相应的difScene.sks文件,所有按钮都已放置。我应该在GameViewController中的哪个位置初始化difScene?@CevatMertDökümcü您可以在当前所在的位置初始化它(
let nextScene=difScene(size:self.size)
),但是您需要使用
fileNamed
而不是
size
调用初始值设定项。哦,好的,初始化后我应该如何调整大小?我尝试过使用“nextScene?.size=self.size”,但没有成功。我目前正在成功地进行第二次世界大战,但它比intended@CevatMertDökümcü是否设置新场景的
scaleMode
?使用
GameViewController.swift
中的代码作为参考。