如何通过父节点进行点击?

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 使用负数。它确实让事情变得更加混乱。