Swift 带有zPosition的SpriteKit问题

Swift 带有zPosition的SpriteKit问题,swift,sprite-kit,Swift,Sprite Kit,我在SpriteKit场景中遇到了节点位置问题 我正在构建一个管理器节点,它支持对节点zPosition进行“类似层”的管理,基本上可以让您摆脱对zPosition属性的手动管理,而是使用addNodeUnder(node:SKNode)等方法添加节点,还可以创建组 下面是我制作的一个测试场景: 问题是,对于我所做的操作,绿色和黄色节点应该位于红色节点的顶部 我制作了自己的小调试器,按层次顺序显示SceneKit“场景图”: Node of type LMManagerNode has zP

我在SpriteKit场景中遇到了节点位置问题

我正在构建一个管理器节点,它支持对节点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确实使黄色节点位于红色节点的顶部。怎么可能呢

编辑#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框架方法来显示它,因此我的调试器的输出绝对正确。

下面是您现在对代码的期望

 -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只是从父节点中减去,然后屏幕将绘制所有节点


为了解决这个问题,您需要创建一个自定义类来重写
addChild
函数,并在另一个变量(可能是字典)中跟踪
zPosition
,然后将子zPosition设置为零,并使用
insertChild(node:,atIndex:)
使用此新变量在子数组中按顺序排列子对象,以保持顺序。然后,如果你变得更疯狂,你必须跟踪孩子何时改变其位置,并使用上面的样式在数组中正确设置它

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

当您考虑z位置时,下面是节点树的结构 呈现:

  • 计算每个节点的全局z位置
  • 节点按从最小z值到最大z值的顺序绘制
  • 如果两个节点共享相同的z值,则先渲染祖先节点,然后按子级顺序渲染同级节点
  • 在哪里

    使用此公式,节点的全局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位置到最低全局z位置(基于规则1和规则2),节点在场景中的显示顺序为

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

    这是最终(反向)抽签顺序

    red                0
    yellow           -50
    green           -100
    blue            -100 (parent was added to scene before green's great grandparent)
    

    我认为情况发生了变化,父节点内的节点不再以某种方式尊重zPosition,您是否尝试设置黄色和绿色节点zPosition而不是父节点zPosition,并查看它是否位于顶部?这是有线的:
    yellowNode.zPosition=1000
    使黄色节点位于红色节点的顶部。怎么可能?回答?你的意思是评论,我目前正在为你键入一个答案我建议你阅读标题为@TrevörAnneDenise的部分是的,我理解,我的意思是,你可以将普通的SKNode作为容器节点来模拟问题,将SKSpriteNode作为精灵,而不是使用真正的代码…哦,非常感谢你的回答!这是一种天生的行为。。。但这是基于性能的原因。实际上,我已经在使用字典了,因为它们的计算成本不会随着场景中节点的数量成比例增加。我想我会用它来计算我应该给孩子们的位置。
    red                0
    yellow           -50
    green           -100
    blue            -100 (parent was added to scene before green's great grandparent)