以编程方式添加SKReferenceNode

时间:2016-04-03 17:47:29

标签: swift sprite-kit skscene

我有2d级别所以我把它分成更多的.sks文件。我有" GameScene"我可以通过拖放操作在场景编辑器中加入它们。它创建了SKReferenceNodes。我成功地做到了这一点。但我想在代码中需要时懒洋洋地加载这些部分(它被认为是一种很好的做法)。我失败了。

这是代码的特殊部分:

if let nextPart = SKReferenceNode(fileNamed: "Scene2_city2") {
        if self.childNodeWithName("Scene2_city2") == nil {
            self.addChild(nextPart)
        }
    }

" Scene2_city2"是.sks文件的名称,也是文件中的场景名称。

运行代码我收到错误:

  

***由于未被捕获的异常终止应用程序'无法添加正文,已经存在于一个世界中,原因:'无法添加正文类型:表示对象:[名称:' Scene2_city2& #39; frame:{{ - 0,-0},{1024,768}} anchor:{0,0}},已经存在于一个世界中'

这很奇怪,因为我在添加之前先检查它。

问题:如何以编程方式将SKReferenceNode添加到SKScene?

编辑:这是bitbucket上的simple example project。添加参考场景以进行点击。

4 个答案:

答案 0 :(得分:9)

我找到了一种解决方法,但事实证明使用SKReferenceNode方法创建URL时没有问题。 例如:

let path = NSBundle.mainBundle().pathForResource("SpaceShip", ofType: "sks")
let spaceShip = SKReferenceNode (URL: NSURL (fileURLWithPath: path!))
addChild(spaceShip)

我做了一点挖掘,当使用SKReferenceNode创建fileNamed时,它出现在7.3.1 vs 7.2.1中,现在它返回一个可选项。打开时,你会得到SKScene,如果你尝试将它作为一个孩子添加到现有场景中,它当然会抛出错误。

添加了快速7.3测试项目https://github.com/cocojoe/SKReferenceNodeIssue/tree/workaround

请注意,您在Apple论坛上引用了我的帖子。我填写了一个月前的错误报告,根据过去的经验,这些可能需要一段时间才能看到。

答案 1 :(得分:1)

您已检查节点是否在场景的层次结构中。此错误与物理世界有关,它与节点已添加到场景中的事实无关。

我个人无法使用SKReferenceNode重现您所说的内容,但这可能是因为我并不完全了解您当前的设置。

如果两个节点指向同一个SKPhysicsBody实例,则会发生此错误,如下所示:

override func didMoveToView(view: SKView) {

        let sprite = SKSpriteNode(color: .purpleColor(), size: CGSize(width: 20, height: 20))
        let sprite2 = SKSpriteNode(color: .purpleColor(), size: CGSize(width: 20, height: 20))

        sprite.position =  CGPoint(x:frame.midX, y:frame.midY)
        sprite2.position = CGPoint(x:frame.midX, y:frame.midY + 100)

        let sharedPhysicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: -10, height: -10))

        sprite.physicsBody = sharedPhysicsBody
        sprite2.physicsBody = sharedPhysicsBody

        addChild(sprite)
        addChild(sprite2)
    }

此代码将因您当前收到的错误而崩溃。因此,检查您是否在某处或类似地使用相同的SKPhysicsBody,您将解决此问题。

答案 2 :(得分:1)

我遇到了同样的问题。如果我使用SKReferenceNode(fileNamed :)从scene.sks文件中存在的sprite创建一个新的sprite我得到错误

'无法添加身体,已经存在于一个世界中

这似乎与物理有关,并且在使用addChild将对象添加到场景时发生。如果将物理体设置为零,则错误消失。类似的东西:

let newBox = SKReferenceNode(fileNamed: "Box")
newBox?.physicsBody = nil
newBox?.position = location
addChild(newBox!)

有趣的是,即使将physics选项设置为none,也会出现错误。上面的解决方案适用于这种情况,但你失去了物理机构。

对我来说似乎有用的是创建一个用作源对象的对象,并使用skNode.copy()创建它的副本。

答案 3 :(得分:0)

我找到了另一种不会迫使你将physicsBody设置为nil的解决方法。

就我而言,我用SKScene替换了SKReferenceNode。

我首先确保在我的.sks场景中,所有SKSpriteNodes都是一个主节点的子节点。它不必是一个直接的链接,你仍然可以尊重场景的层次结构,但重要的是在层次结构树的末尾#34;它们链接到一个节点,在我的例子中是背景,但它也可以是一个空节点。

enter image description here

在我的GameScene文件中,我编写了以下代码:

class GameScene: SKScene {
    var mainNode: SKNode? = nil
    override func didMove(to view: SKView) {
        var mySksScene = SKScene(fileNamed: "Caribbeans")
        mainNode = upperBackground?.childNode(withName: "backgroundCaribbean")
        mainNode?.removeFromParent()
        mySksScene = nil
        addChild(mainNode)
    }
}

我首先声明了一个可选的SKNode变量。然后,在didMove(:to :)中,我将.sks文件加载到可选的SKScene()变量中。然后我将SKNode设置为主节点,该节点是所有其他节点的父节点(在我的例子中:backgroundCaribbean)。然后我从我的父场景中删除了我的mainNode,然后设置为nil用于包含.sks场景的变量,只有那时我将我的mainNode添加为我的GameScene的Child。