且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在 SpriteKit 中添加到父级时未显示未归档节点

更新时间:2022-10-18 10:33:20

问题不在于是否将其加载为未归档文件,或者我是否将其加载为 SKReferenceNode.虽然在发现并研究了这个 SKReferenceNode 之后,这正是要走的路,并且可能是为此目的而制作的.

问题在于,在场景编辑器中,自定义对象位于场景旁边 (x = -1500),因为当我最初构建它时,它位于 scene.sks 文件中,我不希望它位于场景顶部对象.当我将它转移到它自己的 sks 文件时,它保持了它的定位.我认为这没什么大不了的,因为在将 sks 文件加载到变量中后,我在代码中将其位置设置为 CGPoint(x: 0, y: 0) .问题是您不能在现有场景周围移动加载的场景对象,因此如果它不在屏幕上,它将保持在屏幕外.设置位置没有任何作用,无论它是未归档文件还是 SKReferenceNode 都不会移动.

所以我引用了 sks 文件中的第一个孩子并设置了它的位置和中提琴!

如果有人对此设置可以做什么感兴趣,您可以在他们自己的 sks 文件中创建和布局复杂的自定义对象,然后将它们加载到您的场景文件中.这样做的好处是您的 sks 文件不会变得混乱,然后您的自定义对象 sks 可以在多个不同的场景中引用.

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

Previously I was questioning if i could use the Scene editor to create complex SKSpriteNodes vs just using it to layout SKScenes. With the help of @Anton Rogachevskyi the previous question I started using unarchiveNodeFromFile to locate the .SKS file. It loads the sks file as I would expect, but when I try to add it to the current scene nothing appears. If I break on the addChild line and preview the object it displays in the preview window properly, so I know it is finding the correct file. Inside the sks file is a custom dialog class and setting breakpoints in "required init?(coder aDecoder: NSCoder)" I can tell that the custom object is getting initialized properly.

inside the dialog class I programmatically add a pink box to the object to show that it does reach the init of the class

class TeamDialog: SKSpriteNode {

init(size: CGSize) {
    super.init(texture: nil, color: .red, size: size)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    setup()
}

func setup() {

    let pinkBox = SKSpriteNode(color: .magenta, size: CGSize(width: 100, height: 100))
    pinkBox.zPosition = 500
    addChild(pinkBox)
}
}

And in the Scene this is how I find the object and try to add it to the scene, it appears in the preview but nothing shows up on the screen

private func displayDialog() {

    if let wtf = unarchiveNodeFromFile(file: "TeamDialog")! as SKNode? {

        let layer = SKSpriteNode(color: .clear, size: self.size)
        layer.zPosition = 5000
        layer.position = CGPoint(x: self.size.width / 2, y: self.size.height / 2)
        addChild(layer)

        for child in wtf.children {
            print("child (child.name)")
            if let teamDialog = child as? TeamDialog {
                teamDialog.removeFromParent()
                layer.zPosition = 1
                layer.addChild(teamDialog)
            } 
        }
    }
}

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

Again, I can see it in the preview window but nothing appears when it is added to the scene.

Do I have to handle an object that has been unarchived differently or do something to it before I can add it to the scene?

I pulled the code out and have put it in a test project with the same results.

I've tried adding the sks file (as a node) to the scene with no luck, and i've tried isolating out the dialog from the sks file and adding it with no luck

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