В SpriteKit, как zPosition используется для рендеринга и для проверки попадания?

Редактировать: Apple исправила это в iOS8, так что это, конечно, не ожидалось / предназначено, но ошибка.

Похоже, что zPosition интерпретируется по-разному, когда используется для рендеринга узла против, когда используется для определения, к какому узлу прикоснулись.

Когда я создаю иерархию родительских и дочерних узлов (все с установленным zPosition), самый верхний узел для рендеринга определяется суммированием всех zPosition s, ведущих к узлу, поэтому узлы от разных родителей могут чередоваться.
Однако при определении самого верхнего узла для получения касаний zPosition используется только для того, чтобы различать братьев и сестер одного и того же родителя, когда узлы имеют другого родителя, их родительский z-порядок имеет приоритет. (все дочерние элементы одного из родителей находятся ниже или выше узлов другого родителя)

Для иллюстрации приведем пример кода с результатами:

#import "MyScene.h"

@interface NodeWithHitTest : SKSpriteNode
-(instancetype)initWithColor:(UIColor *)color size:(CGSize)size;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
@end


@implementation NodeWithHitTest
-(instancetype)initWithColor:(UIColor *)color size:(CGSize)size {
    self = [super initWithColor:color size:size];
    self.userInteractionEnabled = YES;
    return self;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"%@ hit", self.name);
}
@end

@implementation MyScene

-(id)initWithSize:(CGSize)size {    
    if (self = [super initWithSize:size]) {
        SKNode* container1 = [SKNode new];
        SKNode* container2 = [SKNode new];
        NodeWithHitTest* sprite1 = [NodeWithHitTest spriteNodeWithColor:[UIColor yellowColor] size:CGSizeMake(200, 200)];
        sprite1.name = @"yellow";
        sprite1.position = CGPointMake(self.size.width/2, self.size.height/2);
        NodeWithHitTest* sprite2 = [NodeWithHitTest spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(150, 150)];
        sprite2.name = @"blue";
        sprite2.position = sprite1.position;
        NodeWithHitTest* sprite3 = [NodeWithHitTest spriteNodeWithColor:[UIColor redColor] size:CGSizeMake(100, 100)];
        sprite3.name = @"red";
        sprite3.position = sprite1.position;

        [container1 addChild:sprite1];
        [container1 addChild:sprite3];
        [container2 addChild:sprite2];

        [self addChild:container1];
        [self addChild:container2];
//        sprite1.zPosition = 1;
//        sprite2.zPosition = 2;
//        sprite3.zPosition = 3;
    }
    return self;
}

@end

При запуске с закомментированными строками zPosition вы получите следующий результат:
без zPosition

Как и ожидалось, первый контейнер1 отображается (с желтым и красным квадратом), а сверху контейнер2 отображается (с синим квадратом), поэтому красный квадрат скрывается. При щелчке внутри желтой "границы", вывод yellow hit, щелкнув внутри синих квадратных отпечатков blue hitвсе как положено.

Однако, когда строки zPosition вставлены, вы получите следующее:
с zPosition

Как вы можете видеть, синий квадрат из container2 чередуется с двумя квадратами container1, однако, когда вы щелкаете внутри красного квадрата, вы получаете blue hit!
При определении, какой узел является самым верхним для касаний, все, что находится в контейнере 2, все еще находится над контейнером 1.

Это ожидаемое поведение? И если так, есть ли общий способ справиться с этим, не теряя здравомыслия?

2 ответа

Решение

Я не знаю, изменилось ли что-нибудь с вашего поста или вы просто что-то сделали не так, но в моем случае это сработало.

Я просто копирую, вставляю твой код в свежий проект и проверяю его.

Я получаю красный удар, если красный квадрат находится сверху, и я получаю синий квадрат, если синий квадрат находится сверху.

Да, это ожидаемое поведение. Z-позиции для рисования и для касания не идентичны. В то время как есть что-то вроде глобальной z-позиции для отрисовки, та, которая определяет, к какому узлу прикоснулись, относительно родителя (и их z-отношения друг к другу).

Другие вопросы по тегам