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

Posted

技术标签:

【中文标题】在 SpriteKit 中添加到父级时未显示未归档节点【英文标题】:Unarchived Node doesn't appear when added to parent in SpriteKit 【发布时间】:2017-01-30 18:41:07 【问题描述】:

以前我在质疑是否可以使用场景编辑器来创建复杂的 SKSpriteNode,而不是仅使用它来布局 SKScene。在@Anton Rogachevskyi the previous question 的帮助下,我开始使用 unarchiveNodeFromFile 来定位 .SKS 文件。它按我的预期加载了 sks 文件,但是当我尝试将它添加到当前场景时,什么也没有出现。如果我打破 addChild 行并正确预览它在预览窗口中显示的对象,那么我知道它正在找到正确的文件。在 sks 文件中是一个自定义对话框类,并在“required init?(coder aDecoder: NSCoder)”中设置断点我可以看出自定义对象正在正确初始化。

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

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)


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

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
    

再次,我可以在预览窗口中看到它,但是当它添加到场景中时什么都没有出现。

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

我把代码拿出来放在一个测试项目中,结果相同。

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

【问题讨论】:

这些问题太棒了。完全不同的彻底性和趣味性。 谢谢,非常感谢。我对 SpriteKit 的看法是,我需要开始从中获得更多功能,因为等待 Apple 提供功能或支持似乎是一个失败的原因。 从记忆中,ios 8 到 9 发现的错误比添加到 SpriteKit 的功能要多。 iOS 10 添加了草挥动的 SKWarpNode 和其他我忘记的东西。虽然它肯定是惊人的 在了解了你的问题之后,我确定你有和尚树一样的耐心。像这样使用 SK 场景编辑器一定是令人愤怒的——难以置信。我的意思是没有您在使用 .sks 和取消归档时遇到的问题。惊人的耐心。 你用 SKReferenceNode 试过了吗? 【参考方案1】:

问题不在于是否将其加载为未归档文件,或者我是否将其加载为 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")
    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 中添加到父级时未显示未归档节点的主要内容,如果未能解决你的问题,请参考以下文章

Swift 3.0:当给定非 SKView 父级时,SKSpriteNode 作为 Button 不起作用?

停止:从传播到父级的活动状态

在 iphone 应用程序中制作 ipa 文件时未显示配置文件

Nhibernate 在子集合更新时未检测到父项的更改

核心数据父子关系

尝试从父级 IOS swift 3 中删除子级时,我的代表为零