编辑:Apple 在 iOS8 中修复了这个问题,所以这当然不是预期/有意的,而是一个错误。
zPosition
当用于渲染节点与用于确定哪个节点被触摸时,它的解释似乎不同。
当我创建父节点和子节点的层次结构(都设置了 zPosition)时,用于渲染的最顶层节点由通向该节点的所有 zPosition 的总和确定,因此可以交错来自不同父节点的节点。
然而,在确定接收触摸的最顶层节点时,zPosition 仅用于区分同一父节点的兄弟节点,当节点具有不同父节点时,其父节点 z-order 优先。(一个父节点的所有子节点都位于不同父节点的节点之下或之上)
为了说明,一些带有结果的示例代码:
#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 行的情况下运行时,您会得到以下结果:
正如预期的那样,第一个 container1 被渲染(带有黄色和红色方块),在顶部 container2 被渲染(带有蓝色方块),所以红色方块被隐藏了。在黄色“边框”内单击时,输出为yellow hit
,在蓝色正方形内单击会打印blue hit
,一切都符合预期。
但是,当插入 zPosition 线时,您会得到以下信息:
如您所见,容器 2 的蓝色方块与容器 1 的两个方块交错,但是当您在红色方块内单击时,您会得到blue hit
!
在确定哪个节点最适合触摸时,container2 中的所有内容仍位于 container1 之上。
这是预期的行为吗?如果是这样,是否有一种通用的方法可以在不失去理智的情况下处理这个问题?