SpriteKit 与 zPosition 的问题

Tre*_*vör 4 sprite-kit swift

我在 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.
Run Code Online (Sandbox Code Playgroud)

如你看到的 :

  • 红色节点包含在具有zPosition = 0
  • 蓝色节点包含在一个节点内,该节点具有zPosition = -100
  • 黄色和绿色节点包含在组节点内,该组节点本身包含在具有以下属性的节点内:zPosition = 100

既然包含红色节点的节点有zPosition = 0,并且包含绿色和黄色节点的节点有zPosition = 100,那么这两个节点不应该在红色节点的 顶部吗?

顺便说一句,ignoresSiblingOrder我的SKView设置为...false

编辑:这很奇怪:yellowNode.zPosition = 1000 确实使黄色节点位于红色节点之上。怎么可能?

编辑#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)
}
Run Code Online (Sandbox Code Playgroud)

如您所见,我仅使用 SpriteKit 框架方法来显示它,因此我的调试器的输出绝对是正确的。

Eps*_*lon 5

从苹果的文档来看,

\n
\n

z 位置是 node\xe2\x80\x99s 相对于其父节点的高度,就像 node\xe2\x80\x99s 位置属性表示其相对于父\xe2\x80\x99s 位置的 x 和 y 位置一样。因此,您可以使用 z 位置将节点放置在 Parent\xe2\x80\x99s 位置的上方或下方。

\n
\n

\n
\n

当您考虑 z 位置时,节点树的渲染方式如下:\n

\n
    \n
  1. 计算每个节点\xe2\x80\x99的全局z位置。
  2. \n
  3. 节点按从最小 z 值到最大 z 值的顺序绘制。
  4. \n
  5. 如果两个节点共享相同的 z 值,则先渲染祖先节点,然后按子节点顺序渲染兄弟节点。
  6. \n
\n
\n

在哪里

\n
node's global z position = node's z position + node's parent's z position + node's parent's parent's z position + ...\n
Run Code Online (Sandbox Code Playgroud)\n

使用此公式,节点的全局 z 位置为

\n
red is 0        (0 + 0 + 0)\nblue is -100    (0 + -100 + 0)\nyellow = -50    (-150 + 0 + 100 + 0)\ngreen = -100    (-200 + 0 + 100 + 0)\n
Run Code Online (Sandbox Code Playgroud)\n

从最高到最低的全局 z 位置(基于规则 1 和 2),节点在场景中出现的顺序为

\n
red\nyellow\ngreen / blue\n
Run Code Online (Sandbox Code Playgroud)\n

其中红色出现在黄色之上,黄色出现在绿色/蓝色之上。由于绿色和蓝色具有相同的全局 z 值,因此使用兄弟顺序(规则 3)来确定绘制顺序。在本例中,绿色的顶级LMWarpperNode节点(即,其曾祖父母)被添加到LMManagerNode蓝色LMWarpperNode节点之后的节点,因此首先绘制蓝色,然后在蓝色上绘制绿色。

\n

这是最终的(相反的)抽签顺序

\n
red                0\nyellow           -50\ngreen           -100\nblue            -100 (parent was added to scene before green's great grandparent)\n
Run Code Online (Sandbox Code Playgroud)\n