В 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 вы получите следующий результат:
Как и ожидалось, первый контейнер1 отображается (с желтым и красным квадратом), а сверху контейнер2 отображается (с синим квадратом), поэтому красный квадрат скрывается. При щелчке внутри желтой "границы", вывод yellow hit
, щелкнув внутри синих квадратных отпечатков blue hit
все как положено.
Однако, когда строки zPosition вставлены, вы получите следующее:
Как вы можете видеть, синий квадрат из container2 чередуется с двумя квадратами container1, однако, когда вы щелкаете внутри красного квадрата, вы получаете blue hit
!
При определении, какой узел является самым верхним для касаний, все, что находится в контейнере 2, все еще находится над контейнером 1.
Это ожидаемое поведение? И если так, есть ли общий способ справиться с этим, не теряя здравомыслия?
2 ответа
Я не знаю, изменилось ли что-нибудь с вашего поста или вы просто что-то сделали не так, но в моем случае это сработало.
Я просто копирую, вставляю твой код в свежий проект и проверяю его.
Я получаю красный удар, если красный квадрат находится сверху, и я получаю синий квадрат, если синий квадрат находится сверху.
Да, это ожидаемое поведение. Z-позиции для рисования и для касания не идентичны. В то время как есть что-то вроде глобальной z-позиции для отрисовки, та, которая определяет, к какому узлу прикоснулись, относительно родителя (и их z-отношения друг к другу).