Scene Created in Sprite Kit Level Editor Is Not Working

Scene created in Sprite kit level editor is not working

It may be transition to a grey scene due to spelling errors or the file not even being in the mainBundle. I have tested this and it works. You need to make sure that you are writing the exact name of the .sks file when loading or else you get a grey screen.

Example

If the file is called GameScreen.sks and the class is called GameScene then if you put the class name when loading the .sks file you will get a grey screen.

let doors = SKTransition.doorwayWithDuration(1.0)
let archeryScene = GameScene(fileNamed: "GameScreen")
self.view?.presentScene(archeryScene, transition: doors)

So if we look at the second line of code, We see that it is loading the .sks file with the name GameScreen opposed to the class name GameScene. We also abort using the file extension because the compiler know by default it is a .sks file we are searching for in the mainBundle.

If you do keep getting a grey screen, Then it may be an error in spelling or ing you GameViewController, In the SKNode Extension, Be sure to change

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

to this..

 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 SKScene
archiver.finishDecoding()
return scene
} else {
return nil
}
}
}

We just edited this line of code,

 let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as GameScene

to this

 let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as SKScene

This will allow us to load multiple .sks files without any errors or crashes.

SpriteKit reference nodes from level editor

you will have to loop through the children of the scene and assign them to local objects to use in your code

assuming your objects in your SKS file were named Obstacle1, Obstacle2, Obstacle3

Once in local objects you can check and do whatever you want with them

let obstacle1 = SKSpriteNode()
let obstacle2 = SKSpriteNode()
let obstacle3 = SKSpriteNode()
let obstacle3Location = CGPointZero


func setUpScene() {

self.enumerateChildNodesWithName("//*") {
node, stop in

if (node.name == "Obstacle1") {
self.obstacle1 = node
}
else if (node.name == "Obstacle2") {
self.obstacle2 = node
}
else if (node.name == "Obstacle3") {
self.obstacle3Location = node.position
}
}
}

Do I need to create a new SpriteKit level editor file for every new .swift file?


Short Answer. Yes.

Reason..

Every time you want to present or load an .sks file, You need to load it with a class like so

let doors = SKTransition.doorwayWithDuration(1.0)
let archeryScene = GameScene(fileNamed: "GameScene")
self.view?.presentScene(archeryScene, transition: doors)

If you look a the constant loads the file with a class

MyScene(fileNamed: "MyScene")

So yeah you do need a .swift file for each .sks file.

For more info on .sks files look here.

Techotopia - An iOS 8 Swift Sprite Kit Level Editor Game Tutorial

Also when I use the Spritekit Level Editor, I usually set the Scene size to 960 x 640 to support the smallest iPhone. Alsong as you have @1x, @2x, @3x and possibly @1x~iPad and @2x~iPad, Everything will be fine. Just to be sure in the ViewDidLoad or the initWithSize(CGSize) to add self.scaleMode = .AspectFill. You can set it to what ever it may be. Your options are,

SKSceneScaleMode.Fill

Each axis of the scene is scaled independently so that each axis in the scene exactly maps to the length of that axis in the view.

SKSceneScaleMode.ResizeFill

The scene is not scaled to match the view. Instead, the scene is automatically resized so that its dimensions always matches those of the view.

SKSceneScaleMode.AspectFit

The scaling factor of each dimension is calculated and the smaller of the two is chosen. Each axis of the scene is scaled by the same scaling factor. This guarantees that the entire scene is visible, but may require letterboxing in the view.

SKSceneScaleMode.AspectFill

The scaling factor of each dimension is calculated and the larger of the two is chosen. Each axis of the scene is scaled by the same scaling factor. This guarantees that the entire area of the view is filled, but may cause parts of the scene to be cropped.

(Credits to @epicbyte - Dealing with different iOS device resolutions in SpriteKit)

Level Editor for Sprite Kit?

Here's a list. In alphabetical order, as of July 5th, 2015:

Available:

  • Level Helper 2 apparently supports Sprite Kit (link to docs)
  • Sprite Kit Designer is designed specifically for Sprite Kit but has not been updated since April 2014 (possibly discontinued?)
  • Xcode has a Sprite Kit Scene Editor built-in (Scene Editor)

Not (yet) available

  • SpriteBuilder v1.1 beta had experimental support for Sprite Kit (w/o physics) but this feature was dropped.

If you know a Sprite Kit (or compatible) visual design tool that's not listed here please add it as a comment. I will update the list infrequently.

Unarchived Node doesn't appear when added to parent in SpriteKit

The problem wasn't whether or not Loaded it as an unarchived file or if I loaded it as a SKReferenceNode. Although after finding out about and researching this SKReferenceNode is EXACTLY the way to go and was probably made for this purpose.

The problem was that in the scene editor the custom object was positioned beside the scene (x = -1500) because when I originally constructed it was in the scene.sks file and I didn't want it on top of the scene objects. when I transferred it to it's own sks file it kept it's positioning. I didn't think that this was a big deal because after I loaded the sks file into a variable I set it's position to CGPoint(x: 0, y: 0) in code. The problem is that you CANNOT move the loaded scene object around the existing scene, so if it is off screen it will stay offscreen. Setting the position did nothing, and it didn't matter if it was an unarchived file or SKReferenceNode it wouldn't move.

So i referenced the first child in the sks file and set it's position and viola!

If anyone is interested at what can be done with this setup, you can create and layout complex custom objects in their own sks file and then load them into your scene file. The beauty of doing it this way is that your sks files don't become cluttered and then your custom object sks's can be reference in multiple different scenes.

    let path = Bundle.main.path(forResource: "TeamDialog", ofType: "sks")
let dialogScene = SKReferenceNode (url: URL (fileURLWithPath: path!))
if let teamDialog = dialogScene.childNode(withName: "//teamDialog") as? TeamDialog {
teamDialog.setup(scene: self)
teamDialog.position = CGPoint(x: 0, y: 0)
dialogScene.zPosition = 5000
addChild(dialogScene)
}


Related Topics



Leave a reply



Submit