SKEffectNode ignores children zPosition order

Number:rdar://16534245 Date Originated:2014-04-05
Status:Closed Resolved:2014-06-03
Product:iOS SDK Product Version:7.1
Classification:UI Reproducible:Always
SKEffectNode ignores the zPosition order of its child nodes. It seems to instead render as if zPosition were the same for each node; in other words, the SKEffectNode may be rendering its children in the order they were added.

Steps to Reproduce:
1. Add an SKEffectNode to the scene.
2. Add node X with zPosition 1.
3. Add overlapping node Y with zPosition 0.

Create a new iOS Xcode project (or use the attached tarball) using the Sprite Kit template. Replace the scene class's implementation with the following code. Note the if-statement inviting you to test the workaround.

Expected Results:
Node X should render on top of Node Y, since its zPosition is higher.

Actual Results:
Node Y renders on top of Node X. Possibly because Node Y was added after Node X.

iOS 7.1 (11D167)

One workaround is to interject an ordinary SKNode. Add all the SKEffectNode's children to this SKNode, then add this SKNode to the SKEffectNode. This restores the zPosition-based drawing order.

Perhaps SKEffectNode should expose a property like SKView's ignoresSiblingOrder?

iPhone 5S
iOS Simulator



Attached a sample Xcode project to demonstrate the problem. It's also included at the bottom of this comment.

Both the effect and normal nodes have two children: red and green sprite nodes. The green sprite node has zPosition 10. The red sprite node has zPosition 5. Thus, in both cases, the green sprite node should render over the red sprite node. This is what happens with the normal SKNode on the lower half of the screen. However with the effect SKEffectNode on the upper half of the screen, the red sprite node incorrectly renders over the green sprite node.

Note the if-statements on RPGMyScene.m's line 26 inviting you to test the workaround.

-(id)initWithSize:(CGSize)size {
    if (self = [super initWithSize:size]) {
        SKEffectNode *effect = [SKEffectNode node];
        SKNode *normal = [SKNode node];

        effect.position = CGPointMake(size.width / 2, size.height * .75f);
        normal.position = CGPointMake(size.width / 2, size.height * .25f);

        [self addChild:effect];
        [self addChild:normal];

        NSArray *parents = @[effect, normal];

        if (0) {
            SKNode *intermediate = [SKNode node];
            [effect addChild:intermediate];
            parents = @[intermediate, normal];

        for (SKNode *parent in parents) {
            SKSpriteNode *over = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(100, 100)];
            SKSpriteNode *under = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(100, 100)];

            over.position = CGPointMake(-25, 0);
            under.position = CGPointMake(25, 0);

            over.zPosition = 10;
            under.zPosition = 5;

            [parent addChild:over];
            [parent addChild:under];
    return self;

Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!