Using Swift and SpriteKit, I have a problem with SKSpriteNode not showing when being added as a child to another SKSpriteNode. In contrast, a SKLabelNode put in exactly the same place does show up.
// does not show up, expected a white square
override func renderBody(parentNode: SKNode, position: CGPoint) {
let node = SKSpriteNode(color: UIColor.whiteColor(), size: CGSize(width: 48, height: 48))
node.position = position
parentNode.addChild(node)
}
// does show up as white text in the correct position
override func renderBody(parentNode: SKNode, position: CGPoint) {
let node = SKLabelNode(text: "hello")
node.position = position
parentNode.addChild(node)
}
'parentNode' and 'position' is the same in both cases.
'parentNode' is a larger SKSpriteNode, created with a texture in dark colors, covering the screen as a background.
'position' is CGPoint(x: 50, y: 50).
It looks like that the rectangle sprite gets below the background, while the label sprite gets on top. I experimented by removing the background and adding the rectangle sprite directly to the scene node, and then it does show up.
Does anybody have an idea of what can be wrong?
Edit: Setting the zPosition manually solves the problem. However, I still think there's something which is wrong somewhere. You shouldn't need to set it manually on a child node in order to avoid having its parent node hiding the child. I never had to do this in Xcode 5. And why is there a difference between a labelnode and a sprite node?
Here's an example which hopefully illustrates it better. Create a default SpriteKit, Swift, Iphone project in Xcode 6. Paste the code below into the for-loop in touchesBegan. Remove the "Hello World" label created in didMoveToView. Run it and click somewhere in the middle of the screen.
let location = touch.locationInNode(self)
// LabelNode without manually setting zposition
// visible
let backGround1 = SKSpriteNode(imageNamed:"Spaceship")
backGround1.position = CGPoint(x: location.x, y: location.y + 250)
backGround1.xScale = 0.5
backGround1.yScale = 0.5
self.addChild(backGround1)
let labelNode = SKLabelNode(fontNamed: "ChalkDuster")
labelNode.text = "I am on top"
labelNode.fontSize = 48
labelNode.fontColor = UIColor.yellowColor()
backGround1.addChild(labelNode)
// SpriteNode without manually setting zposition
// hidden under its parent node
let backGround2 = SKSpriteNode(imageNamed:"Spaceship")
backGround2.position = location
backGround2.xScale = 0.5
backGround2.yScale = 0.5
self.addChild(backGround2)
let spriteNode2 = SKSpriteNode(color: UIColor.yellowColor(), size: CGSize(width: 100, height: 100))
backGround2.addChild(spriteNode2)
// SpriteNode with zposition manually set
// visible
let backGround3 = SKSpriteNode(imageNamed:"Spaceship")
backGround3.position = CGPoint(x: location.x, y: location.y - 250)
backGround3.xScale = 0.5
backGround3.yScale = 0.5
self.addChild(backGround3)
let spriteNode3 = SKSpriteNode(color: UIColor.yellowColor(), size: CGSize(width: 100, height: 100))
spriteNode3.zPosition = 0.001
backGround3.addChild(spriteNode3)
What you're looking for is the ignoresSiblingOrder
property on SKView
:
A Boolean value that indicates whether parent-child and sibling relationships affect the rendering order of nodes in the scene.
The default Xcode 6.x (and maybe 5, I haven't checked) SpriteKit template sets that to true
when setting up the SKView
in the view controller. With it set to true
, the order that you add nodes to the scene does not affect their z-position. If you set it to false
, they'll be layered in the order you add them to the scene (or parent node).
That being said, SpritKit can do some optimizations when ignoresSiblingOrder
is true
(which is why that's the default in the template), so it's probably best to keep it that way if at all possible. In that case, you'll have to manually set the zPosition
property of each node though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With