I always thought that the the zPosition of a SKNode would be relative to its parent, but right now I'm experiencing the opposite effect.
I have two parent SKNodes in my scene, which have a zPosition of 1 (node1) and 2 (node2). What I want to achieve is that node2 should ALWAYS be layered ABOVE node1. But unfortunately, the child nodes of node1 (which have a zPosition of 1-50) are all layered above the child nodes of node2 (which currently have no zPosition). Is there any way to solve this (except giving node2 a zPosition of more than 50)? Maybe some kind of boolean Parameter to set all child nodes' zPosition relative to its parent? Any help will be appreciated!
EDIT: To make it more clear, here's the hierarchy of all elements:
EDIT2: Here's a very reduced version of my GameScene class:
import SpriteKit
class GameScene: SKScene {
let gameNode = SKNode()
let node1 = SKNode()
let node2 = SKNode()
let nodeSize:CGFloat = 50.0
let spacing:CGFloat = 5.0
required init(coder aDecoder: NSCoder) {
fatalError("NSCoder not supported")
}
override init(size: CGSize) {
super.init(size: size)
self.addChild(gameNode)
node1.name = "node1"
node2.name = "node2"
node1.zPosition = 1
node2.zPosition = 2
gameNode.addChild(node1)
gameNode.addChild(node2)
// add children to node1
for i in 1..<10 {
let child = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: nodeSize, height: nodeSize))
child.position = CGPointMake((nodeSize + spacing) * CGFloat(i), 0)
child.zPosition = CGFloat(i)
self.node1.addChild(child)
}
// add children to node2
for i in 1..<10 {
let child = SKLabelNode(fontNamed: "Avenir Black")
child.position = CGPoint(x: (nodeSize + spacing) * CGFloat(i), y: 0)
child.text = "label\(i)"
child.fontSize = 10
child.fontColor = UIColor.blackColor()
self.node2.addChild(child)
}
}
}
When you run it, you can see that only the first child of node2 (label1) is layered above the first child of node1 (since they have the same zPosition). All others are layered underneath the children of node1.
When reading the Apple Documentation regarding this, you can find:
Maintaining the order of a node’s children can be a lot of work. Instead, you can give each node an explicit height in the scene. You do this by setting a node’s zPosition property. The z position is the node’s height relative to its parent node, much as a node’s position property represents its x and y position relative to parent’s position. So you use the z position to place a node above or below the parent’s position.
When you take z positions into account, here is how the node tree is rendered:
- Each node’s global z position is calculated.
- Nodes are drawn in order from smallest z value to largest z value.
- If two nodes share the same z value, ancestors are rendered first, and siblings are rendered in child order.
The point I found - which i didn't know it was like this - is that the children zPosition is calculated summating their parents zPosition, so if node1.zPosition + (node1's)child3.zPosition = 4
, and node2.zPosition + (node2's)child3.zPosition = 3
, the node1's child will be painted above.
Solution: Set node2.zPosition
bigger than (node1's)lastChild.zPosition + node1.zPosition
.
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