zPosition 的 SpriteKit 问题
Posted
技术标签:
【中文标题】zPosition 的 SpriteKit 问题【英文标题】:SpriteKit issue with zPosition 【发布时间】:2016-01-06 17:14:36 【问题描述】:我在 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
,那么这两个节点不应该在红色节点的顶部 ?
顺便说一句,我的SKView
的ignoresSiblingOrder
设置为false
...
编辑:这很奇怪:yellowNode.zPosition = 1000 确实使黄色节点位于红色节点之上。怎么可能?
EDIT #2 这是我的调试功能的代码:
func renderNodeHieararchyForNode(node:SKNode, index:Int)
var i = 0
var beginning = ""
while i != index
beginning += " "
i++
if i == index
beginning += " "
print("\(beginning)Node of type \(node.dynamicType) \(node.name != nil ? "('\(node.name!)')" : "") has zPosition = \(node.zPosition)\(node.children.count > 0 ? " and has children :" : ".")")
for (i,child) in node.children.enumerate()
renderNodeHieararchyForNode(child, index: index+1)
if i == node.children.count-1
print("")
func renderNodeHiearchyForNode(node:SKNode)
renderNodeHieararchyForNode(node, index: 0)
如您所见,我只使用 SpriteKit 框架方法来显示它,所以我的调试器的输出肯定是正确的。
【问题讨论】:
我相信事情发生了变化,并且父节点内的节点不再以某种方式尊重 zPosition,您是否尝试设置黄色和绿色节点 zPosition 而不是父母 zPosition,看看是否名列前茅? 这是有线的:yellowNode.zPosition = 1000
确实使黄色节点位于红色节点之上。怎么可能?
回答?您的意思是评论,我目前正在为您输入答案
我建议你阅读标题为Understanding the Drawing Order for a Node Tree的部分
@TrevörAnneDenise 是的,我明白,我的意思是允许您使用常规 SKNode 作为容器节点来模拟问题,而 SKSpriteNode 用于精灵而不是使用真实代码...
【参考方案1】:
来自 Apple 的文档,
z 位置是节点相对于其父节点的高度,就像节点的位置属性表示其相对于父节点的 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
节点(即它的曾祖父母)被添加到蓝色的LMWarpperNode
节点之后的LMManagerNode
节点,因此先绘制蓝色,然后在蓝色上绘制绿色。
这是最终(颠倒的)抽签顺序
red 0
yellow -50
green -100
blue -100 (parent was added to scene before green's great grandparent)
【讨论】:
【参考方案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 只是从 parent 中减去,然后屏幕在 1 次通过所有节点。
为了解决这个问题,您需要创建一个覆盖addChild
函数的自定义类,并在另一个变量(可能是字典)中跟踪您的zPosition
,然后将子zPosition 设置为零,然后使用 insertChild(node:, atIndex:)
将您的孩子按顺序放置在 children 数组中,使用此新变量来保留您的顺序。然后如果你更疯狂,你将不得不跟踪孩子何时更改其 zPosition,并使用上述样式在数组中正确设置它
【讨论】:
哦,非常感谢您的回答!这是 IMO 的一种有线行为......但出于性能原因,这是合理的。 实际上,我已经在使用字典,因为它们的计算成本不会与场景中的节点数量成比例增加。我想我会用它来计算我应该给孩子们的 zPositions。以上是关于zPosition 的 SpriteKit 问题的主要内容,如果未能解决你的问题,请参考以下文章
设置 SKEmitterNode 的“targetNode”会导致奇怪的“zPosition”行为
iOS 7 Sprite Kit 更改 SKAction 中的 zPosition
如何应用SPRITEKIT的CAMERA实现游戏中的ENDLESS无限循环背景