在 SpriteKit 中添加到父节点时未出现未归档的节点 [英] Unarchived Node doesn't appear when added to parent in SpriteKit

查看:24
本文介绍了在 SpriteKit 中添加到父节点时未出现未归档的节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以前我在质疑是否可以使用场景编辑器来创建复杂的 SKSpriteNodes,而不是仅使用它来布局 SKScenes.在@Anton Rogachevskyi

在对话框类中,我以编程方式向对象添加了一个粉红色框,以表明它确实到达了类的init

class TeamDialog: SKSpriteNode {初始化(大小:CGSize){super.init(纹理:无,颜色:.red,大小:大小)}需要初始化?(编码器aDecoder:NSCoder){super.init(编码器:aDecoder)设置()}功能设置(){让pinkBox = SKSpriteNode(颜色:.洋红色,大小:CGSize(宽度:100,高度:100))粉红色Box.zPosition = 500添加孩子(粉红色框)}}

在场景中,这是我找到对象并尝试将其添加到场景中的方式,它出现在预览中,但屏幕上没有任何显示

private func displayDialog() {if let wtf = unarchiveNodeFromFile(file: "TeamDialog")!作为SKNode?{让层 = SKSpriteNode(颜色:.clear,大小:self.size)layer.zPosition = 5000layer.position = CGPoint(x: self.size.width/2, y: self.size.height/2)添加子(层)为孩子在 wtf.children {打印(孩子(孩子.名称)")如果让 teamDialog = child as?团队对话{teamDialog.removeFromParent()layer.zPosition = 1layer.addChild(teamDialog)}}}}func unarchiveNodeFromFile(file: String) ->SK节点?{if let path = Bundle.main.path(forResource: file, ofType: "sks") {让 fileData = NSData.init(contentsOfFile: 路径)let archiver = NSKeyedUnarchiver.init(forReadingWith: fileData as Data!)archiver.setClass(SKNode.classForKeyedUnarchiver(), forClassName: "SKScene")let node = archiver.decodeObject(forKey: NSKeyedArchiveRootObjectKey) as!SK节点archiver.finishDecoding()返回节点} 别的 {返回零}}

同样,我可以在预览窗口中看到它,但是当它被添加到场景中时什么也没有出现.

在我将它添加到场景之前,我是否必须以不同的方式处理一个已取消归档的对象或对其进行一些处理?

我提取了代码并将其放入一个测试项目中,结果相同.

我尝试将 sks 文件(作为节点)添加到场景中但没有成功,并且我尝试从 sks 文件中分离出对话框并在没有运气的情况下添加它

解决方案

问题不在于是将其作为未归档文件加载还是作为 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(场景:自我)teamDialog.position = CGPoint(x: 0, y: 0)dialogScene.zPosition = 5000addChild(dialogScene)}

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

这篇关于在 SpriteKit 中添加到父节点时未出现未归档的节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆