如何通过父节点进行点击?
How to make tap through parent nodes?
我搜索了 SO 并尝试了几个例子,但我仍然无法理解这种行为。在模拟器 7.1 上,tap-through 可以工作,但在 8.1 上不行 work.Also 我之前问过类似的问题,但与此不同,我使用 nodesAtPoint 方法解决了它,然后遍历所有节点并检查节点名称 / class...但这有所不同,因为现在我使用实现 touchesBegan 的自定义按钮 class,我希望它检测并在可能的情况下检测 "swallow" 触摸。
所以我有一个简单的按钮 class,它是 SKSpriteNode 的子class,它有自己的 touchesBegan 和 userInteractionEnabled = YES
。在我的视图控制器中 属性 ignoreSiblingsOrder
设置为 YES
.
这是一个(简化的)示例,它可以产生所描述的行为:
#import "GameScene.h"
@interface Button : SKSpriteNode
-(instancetype)initWithColor:(UIColor *)color size:(CGSize)size;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
@end
@implementation Button
-(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 GameScene
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
self.userInteractionEnabled = NO;
SKNode* root = [SKNode new];
root.name = @"root";
SKNode* layer1 = [SKNode new];
SKNode* layer2 = [SKNode new];
layer1.zPosition = -1;//layer1 and layer2 are just containers
layer2.zPosition = -2;
Button* button = [Button spriteNodeWithColor:[SKColor yellowColor] size:CGSizeMake(100, 100)];
button.name = @"yellow button";
button.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));
[layer1 addChild:button];
[root addChild:layer1];
[root addChild:layer2];
[self addChild:root];
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"Touch detected");
}
@end
我只是不明白为什么这在 8.1 上不起作用...我知道命中测试的顺序与渲染节点的顺序相反,但是实现点击行为的正确方法是什么?所以目前发生的事情是,当我在 7.1 上测试时,我收到消息 "yellow button",但在 8.1 上,我收到消息 "touch detected"(当我打印节点名称时,它显示为 root)。因此我也一直 pointed to file a radar,但正如我所说,我用 nodesAtPoint 而不是 nodeAtPoint 解决了所有问题,所以我没有。因为我认为那不是错误,而是我的错误,因为在 7.1 上一切都很好。这是错误还是其他原因?
具有讽刺意味的是,根据我的计算,这似乎是 7.1 而不是 8.1 的错误。不过我还没有用 7.1 测试过这个。
首先,我无法让您的任何代码与 self.userInteractionEnabled = NO;
一起工作,因为没有任何内容会收到触摸。
zPosition 在您设置 ignoreSiblingsOrder
时使用,但它基于其父级。所以如果 parent 是 -1 并且你添加了一个 0 的 child,它的渲染 zPosition 仍然是 -1。触摸也是如此,但顺序相反。使用 userInteraction 呈现的最后一个获取触摸事件。
希望这是有道理的。查看添加的评论和调试。
#import "GameScene.h"
@interface Button : SKSpriteNode
-(instancetype)initWithColor:(UIColor *)color size:(CGSize)size;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
@end
@implementation Button
-(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 GameScene
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
SKNode* root = [SKNode new];
root.name = @"root";
SKNode* layer1 = [SKNode new];
layer1.name = @"layer1";
SKNode* layer2 = [SKNode new];
layer2.name = @"layer2";
layer1.zPosition = -1;//layer1 and layer2 are just containers
layer2.zPosition = -2;
Button* button = [Button spriteNodeWithColor:[SKColor yellowColor] size:CGSizeMake(100, 100)];
button.name = @"yellow button";
button.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));
//layer1 is at -1 and button does not have a z so it will be -1 in the scene like its parent (-1+0)
[layer1 addChild:button];
//root is 0 layer1 is -1 (along with button) root is above layer1 and will recieve any touches
[root addChild:layer1];
//root is 0 layer2 is -2 layer1 (and button) are above layer2 and root is above layer1 root gets touch
[root addChild:layer2];
//nothing changes except root is added
[self addChild:root];
//button needs to be on same zPosition or higher to get touch
//it is -1 because of parent node + 1 = 0
//best if you do +2 to ensure it is above
// button.zPosition = 2;
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
for (UITouch *touch in touches)
{
CGPoint point = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:point];
NSLog(@"Touch detected: %@", node.name);
}
}
另外,我建议不要对 zPosition 使用负数。它确实让事情变得更加混乱。
我搜索了 SO 并尝试了几个例子,但我仍然无法理解这种行为。在模拟器 7.1 上,tap-through 可以工作,但在 8.1 上不行 work.Also 我之前问过类似的问题,但与此不同,我使用 nodesAtPoint 方法解决了它,然后遍历所有节点并检查节点名称 / class...但这有所不同,因为现在我使用实现 touchesBegan 的自定义按钮 class,我希望它检测并在可能的情况下检测 "swallow" 触摸。
所以我有一个简单的按钮 class,它是 SKSpriteNode 的子class,它有自己的 touchesBegan 和 userInteractionEnabled = YES
。在我的视图控制器中 属性 ignoreSiblingsOrder
设置为 YES
.
这是一个(简化的)示例,它可以产生所描述的行为:
#import "GameScene.h"
@interface Button : SKSpriteNode
-(instancetype)initWithColor:(UIColor *)color size:(CGSize)size;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
@end
@implementation Button
-(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 GameScene
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
self.userInteractionEnabled = NO;
SKNode* root = [SKNode new];
root.name = @"root";
SKNode* layer1 = [SKNode new];
SKNode* layer2 = [SKNode new];
layer1.zPosition = -1;//layer1 and layer2 are just containers
layer2.zPosition = -2;
Button* button = [Button spriteNodeWithColor:[SKColor yellowColor] size:CGSizeMake(100, 100)];
button.name = @"yellow button";
button.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));
[layer1 addChild:button];
[root addChild:layer1];
[root addChild:layer2];
[self addChild:root];
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"Touch detected");
}
@end
我只是不明白为什么这在 8.1 上不起作用...我知道命中测试的顺序与渲染节点的顺序相反,但是实现点击行为的正确方法是什么?所以目前发生的事情是,当我在 7.1 上测试时,我收到消息 "yellow button",但在 8.1 上,我收到消息 "touch detected"(当我打印节点名称时,它显示为 root)。因此我也一直 pointed to file a radar,但正如我所说,我用 nodesAtPoint 而不是 nodeAtPoint 解决了所有问题,所以我没有。因为我认为那不是错误,而是我的错误,因为在 7.1 上一切都很好。这是错误还是其他原因?
具有讽刺意味的是,根据我的计算,这似乎是 7.1 而不是 8.1 的错误。不过我还没有用 7.1 测试过这个。
首先,我无法让您的任何代码与 self.userInteractionEnabled = NO;
一起工作,因为没有任何内容会收到触摸。
zPosition 在您设置 ignoreSiblingsOrder
时使用,但它基于其父级。所以如果 parent 是 -1 并且你添加了一个 0 的 child,它的渲染 zPosition 仍然是 -1。触摸也是如此,但顺序相反。使用 userInteraction 呈现的最后一个获取触摸事件。
希望这是有道理的。查看添加的评论和调试。
#import "GameScene.h"
@interface Button : SKSpriteNode
-(instancetype)initWithColor:(UIColor *)color size:(CGSize)size;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
@end
@implementation Button
-(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 GameScene
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
SKNode* root = [SKNode new];
root.name = @"root";
SKNode* layer1 = [SKNode new];
layer1.name = @"layer1";
SKNode* layer2 = [SKNode new];
layer2.name = @"layer2";
layer1.zPosition = -1;//layer1 and layer2 are just containers
layer2.zPosition = -2;
Button* button = [Button spriteNodeWithColor:[SKColor yellowColor] size:CGSizeMake(100, 100)];
button.name = @"yellow button";
button.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));
//layer1 is at -1 and button does not have a z so it will be -1 in the scene like its parent (-1+0)
[layer1 addChild:button];
//root is 0 layer1 is -1 (along with button) root is above layer1 and will recieve any touches
[root addChild:layer1];
//root is 0 layer2 is -2 layer1 (and button) are above layer2 and root is above layer1 root gets touch
[root addChild:layer2];
//nothing changes except root is added
[self addChild:root];
//button needs to be on same zPosition or higher to get touch
//it is -1 because of parent node + 1 = 0
//best if you do +2 to ensure it is above
// button.zPosition = 2;
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
for (UITouch *touch in touches)
{
CGPoint point = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:point];
NSLog(@"Touch detected: %@", node.name);
}
}
另外,我建议不要对 zPosition 使用负数。它确实让事情变得更加混乱。