Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add SKReferenceNode programmatically

I have long 2d level so I split it into more .sks files. I have "GameScene" where I can join them in Scene editor with drag and drop. It creates SKReferenceNodes. I've done that with success. But I would like to load these parts lazily when it's needed in code (it's said to be good practice). I'm failing on that.

This is particular part of code:

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

"Scene2_city2" is name of .sks file and also name of Scene inside the file.

Running the code I get an error:

*** Terminating app due to uncaught exception 'Cant add body, already exists in a world', reason: 'Cant add body type: representedObject:[ name:'Scene2_city2' frame:{{-0, -0}, {1024, 768}} anchor:{0, 0}], already exists in a world'

This is very strange, because I first check it before I added.

Question: How should I add SKReferenceNode into SKScene programmatically?

EDIT: Here is simple example project on bitbucket. Reference scene is added for tap.

like image 365
jendan Avatar asked Apr 03 '16 17:04

jendan


2 Answers

I've found a workaround, it turns out there are no issues when creating a SKReferenceNode using the URL method. For example:

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

I did a little digging and it appears in 7.3.1 vs 7.2.1 when creating a SKReferenceNode using fileNamed it now returns an optional. When unwrapped you get the SKScene which will of course throw out errors if you try and add it as a child to an existing scene.

Added a quick 7.3 test project https://github.com/cocojoe/SKReferenceNodeIssue/tree/workaround

Notice you referenced my post on the Apple forum. I filled a bug report about a month ago, from past experience these can take a while to be looked at.

like image 73
cocojoe Avatar answered Sep 30 '22 11:09

cocojoe


You have checked if the node is in scene's hierarchy. This error is related to the physics world and it has nothing to do with the fact that a node is already added to the scene.

Personally I couldn't reproduce what you are saying using SKReferenceNode, but that is probably because I am not fully aware of your current setup.

This error can happen if two nodes point to the same SKPhysicsBody instance, like this:

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

This code will crash with the error you are getting currently. So check if you are re-using the same SKPhysicsBody somewhere or something like that and you will solve this.

like image 25
Whirlwind Avatar answered Sep 30 '22 11:09

Whirlwind