我在SpriteKit场景中遇到了节点的zPosition问题。
我正在构建一个管理节点,支持节点zPosition的“层状”管理,实质上使您能够摆脱zPosition属性的手动管理,而是使用addNodeUnder(node:SKNode)
等方法添加节点还要创建组。
问题在于,通过我所做的操作,绿色和黄色节点应该在红色节点的顶部。
我制作了自己的小调试器,按层次顺序显示SceneKit“场景图”:
Node of type LMManagerNode has zPosition = 0.0 and has children :
Node of type LMWarpperNode has zPosition = 0.0 and has children :
Node of type SKSpriteNode ('Red node') has zPosition = 0.0.
Node of type LMWarpperNode has zPosition = -100.0 and has children :
Node of type SKSpriteNode ('Blue node') has zPosition = 0.0.
Node of type LMWarpperNode has zPosition = 100.0 and has children :
Node of type LMGroupNode ('Test group') has zPosition = 0.0 and has children :
Node of type LMWarpperNode has zPosition = -150.0 and has children :
Node of type SKSpriteNode ('Yellow node') has zPosition = 0.0.
Node of type LMWarpperNode has zPosition = -200.0 and has children :
Node of type SKSpriteNode ('Green node') has zPosition = 0.0.
如你所见:
zPosition = 0
zPosition = -100
zPosition = 100
由于包含红色节点的节点具有zPosition = 0
且包含绿色和黄色节点的节点具有zPosition = 100
,因此这两个节点不应该在顶部红色节点?
我的ignoresSiblingOrder
的{{1}}顺便设置为SKView
...
编辑:这很奇怪:yellowNode.zPosition = 1000确实使黄色节点位于红色节点的顶部。怎么可能?
编辑#2以下是我的调试功能的代码:
false
正如您所看到的,我只使用SpriteKit框架方法来显示它,因此我的调试器输出肯定是正确的。
答案 0 :(得分:4)
来自Apple的文档,
z位置是节点相对于其父节点的高度,就像节点的position属性表示相对于父节点的x和y位置一样。因此,您使用z位置将节点放置在父节点的上方或下方。
和
考虑z位置时,节点树的方式如下 渲染:
- 计算每个节点的全局z位置。
- 按照从最小z值到最大z值的顺序绘制节点。
- 如果两个节点共享相同的z值,则首先呈现祖先,并按子顺序呈现兄弟节点。
醇>
,其中
node's global z position = node's z position + node's parent's z position + node's parent's parent's z position + ...
使用此公式,节点的全局z位置为
red is 0 (0 + 0 + 0)
blue is -100 (0 + -100 + 0)
yellow = -50 (-150 + 0 + 100 + 0)
green = -100 (-200 + 0 + 100 + 0)
从最高到最低的全局z位置(基于规则1和2),节点在场景中的显示顺序是
red
yellow
green / blue
其中红色显示在黄色顶部,黄色显示在绿色/蓝色顶部。由于绿色和蓝色具有相同的全局z值,因此使用兄弟顺序(规则3)来确定绘制顺序。在这种情况下,绿色的顶级LMWarpperNode
节点(即其曾祖父母)被添加到蓝色LMManagerNode
节点之后的LMWarpperNode
节点,所以蓝色首先绘制,绿色绘制为蓝色。
这是最终(反向)抽奖顺序
red 0
yellow -50
green -100
blue -100 (parent was added to scene before green's great grandparent)
答案 1 :(得分:2)
以下是您现在对代码的期望
-100: Node
# 0: Node
# 0: Blue
0 : Node
# 0: Node
# 0:Red
100 : Node
# 0: Node
# -200:Green
# -150:Yellow
但真正发生的是这个
-100: Node
: Node
: Blue
: Green
-50 : Yellow
0 : Node
: Node
: Red
100 : Node
: Node
这是因为zPosition只是从父节点中减去,然后屏幕将1遍传递所有节点。
要解决此问题,您需要创建一个自定义类来覆盖addChild
函数并执行一些操作,以便在另一个变量(可能是字典)中跟踪您的zPosition
,然后设置子zPosition为零,并使用insertChild(node:, atIndex:)
使用此新变量将子项按顺序放置在子数组中以保留您的顺序。然后,如果你更疯狂,你必须跟踪一个孩子何时更改其zPosition,并使用上面的样式在数组中正确设置