Sawyer05
Sawyer05

Reputation: 1604

Could not cast value of type 'SKScene'

I created a new Xcode Game project. I stripped the default animations in the project and added a new Swift file and a new .sks both called MenuScene.

In my GameViewController, I replaced references to by GameScene with MenuScene as I want this scene to launch first:

override func viewDidLoad() {
    super.viewDidLoad()

    // Load 'GameScene.sks' as a GKScene. This provides gameplay related content
    // including entities and graphs.
    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 = true
                view.showsNodeCount = true
            }
        }
    }
}

When I try to launch I get the following error:

Could not cast value of type 'SKScene' (0x1105624) to 'Spritekit10.MenuScene' (0x104c38).

If I change it back to GameScene, which appears to have the exact same setup, all seems fine.

Can anyone point me in the right direction with what the problem is with this?

On my MenuScene.sks under Custom Class, I've added MenuScene thinking that was the problem but the error still shows (and the textfield seems to randomly clear itself when I go back to it.

import SpriteKit
import GameplayKit

class GameScene: SKScene {

    override func sceneDidLoad() {

    }
}

.

import SpriteKit
import GameplayKit

class MenuScene: SKScene {

    override func sceneDidLoad() {

    }
}

Upvotes: 6

Views: 1787

Answers (5)

feca
feca

Reputation: 1169

I found something weird. My project name has a "-" character. After I removed this character from Target name, the project could cast scene.rootNode to GameScene.

Upvotes: 1

feca
feca

Reputation: 1169

It works on iOS 10.3.1 for me.

override func viewDidLoad() {
    super.viewDidLoad()

    let fileName = "GameScene"

    // Load 'GameScene.sks' as a GKScene. This provides gameplay related content
    // including entities and graphs.
    guard let scene = GKScene(fileNamed: fileName) else {
        return
    }

    guard let sceneNode = scene.rootNode as? GameScene ?? GameScene(fileNamed: fileName) else {
        return
    }

    // Copy gameplay related content over to the scene
    sceneNode.entities = scene.entities
    sceneNode.graphs = scene.graphs

    // 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 = true
        view.showsNodeCount = true
    }
}

Upvotes: 0

Chigo Godwin Anyaso
Chigo Godwin Anyaso

Reputation: 209

For Xcode 8.0/8.1 , create a swift file named "Menuscene" and an sks file named "Menuscene" too. delete everything in the Menuscene swift file and insert this code

import SpriteKit
import GameplayKit

class Menuscene: SKScene {

override func didMove(to view: SKView) {
    let menutext = SKLabelNode()
    menutext.text = "MEnuscene"
    menutext.position = CGPoint(x: 0, y: 0)
    menutext.fontSize = 120

    self.backgroundColor = UIColor.blue
    addChild(menutext)

}


override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let gamescene = SKScene(fileNamed: "GameScene")
    gamescene?.scaleMode = .fill
    self.scene?.view?.presentScene(gamescene!,transition: SKTransition.doorsCloseHorizontal(withDuration: 1.0))

}

override func update(_ currentTime: TimeInterval) {

  }
}

and in the attribute inspector tab, set name to "Menuscene", hit enter (very important). then on the next tab, set custom class name to "Menuscene",hit enter (very important).

In your Gamescene.swift file, double-check to be sure your class starts with

class GameScene: SKScene {

add this code to your touchesBegan func

   override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let Menuscene = SKScene(fileNamed: "Menuscene")
    Menuscene?.scaleMode = .fill
    self.scene?.view?.presentScene(Menuscene!,transition: SKTransition.doorsOpenVertical(withDuration: 1.0))

    }

finally in your Gameviewcontroller file, delete everything and insert this code

import UIKit
import SpriteKit
import GameplayKit

class GameViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    if let view = self.view as! SKView? {
        // Load the SKScene from 'GameScene.sks'
        if let scene = SKScene(fileNamed: "Menuscene") {
            // Set the scale mode to scale to fit the window
            scene.scaleMode = .aspectFill

            // Present the scene
            view.presentScene(scene)
        }

        view.ignoresSiblingOrder = true

        view.showsFPS = true
        view.showsNodeCount = true
    }
}

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
}
}

you're welcome! you should be able to tap from game screen to menu screen.

Upvotes: 1

Sawyer05
Sawyer05

Reputation: 1604

So I figured out the issue.

For the .sks file, I had to add a name to the scene in the attributes inspector (even though it was blank in the GameScene). Once I done this, the custom class value saved and the file now loads without an error. Not sure if thats a bug or by design.

Upvotes: 3

Knight0fDragon
Knight0fDragon

Reputation: 16827

Your problem is you are trying to upcast an SKScene to a MenuScene.

This cannot be done, I see you have checked your custom class in your sks file to ensure that it is set to MenuScene, but did you make sure you saved it correctly? You need to type it in and hit enter, if you do not, then the scene will not auto save it, and when you leave will clear it out.

Upvotes: 1

Related Questions