Using an .sks file to layout a complex object vs a

2019-06-07 19:05发布

问题:

Is it possible to use the SceneEditor to layout & create a complex Subclass of SKSpriteNode, load that information and create a custom object in your scene based on the sks file?

My scenario is that I have a popup dialogs (which are nothing more than subclasses of SKSpriteNodes) with a lot of children on the dialog. I was hoping to lay it out in the Scene editor similar to how I lay out an SKScene, and then present it in my scene when needed.

I realize that I could just create this object in my GameScene.sks file, but find that those can get easily cluttered, and thought it might be a nicer way to store these dialgos if each had their own sks file.

I've tried extending SKSpriteNode to access the file similar to the Scene file but it didn't work

if let teamDialog = SKSpriteNode.spriteWithClassNamed(className: "TeamDialog", fileName: "TeamDialog.sks") { }

extension SKSpriteNode {

    static func spriteWithClassNamed(className: String, fileName: String) -> SKSpriteNode? {

        guard let dialog = SKSpriteNode(fileNamed: fileName) else {
                return nil
        }

        return dialog
    }
}

回答1:

You can use this delegate https://github.com/ice3-software/node-archive-delegate

Or, smt like this in swift:

class func unarchiveNodeFromFile(file:String)-> SKNode? {
    if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
        var fileData = NSData.dataWithContentsOfFile(path, options: NSDataReadingOptions.DataReadingMappedIfSafe, error: nil)
        var archiver = NSKeyedUnarchiver(forReadingWithData: fileData)
        archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKNode")
        let node = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as SKNode
        archiver.finishDecoding()
        return node
    } else {
        return nil
    }
}

UPDATE for Swift 3 and fix class casting:

func unarchiveNodeFromFile(file:String)-> SKNode? {
    if let path = Bundle.main.path(forResource: file, ofType: "sks") {
        let fileData = NSData.init(contentsOfFile: path)
        let archiver = NSKeyedUnarchiver.init(forReadingWith: fileData as Data!)
        archiver.setClass(SKNode.classForKeyedUnarchiver(), forClassName: "SKScene")
        let node = archiver.decodeObject(forKey: NSKeyedArchiveRootObjectKey) as! SKNode
        archiver.finishDecoding()
        return node
    } else {
        return nil
    }
}