【问题标题】:In SpriteKit, how is zPosition used for rendering and for hit tests?在 SpriteKit 中,zPosition 如何用于渲染和命中测试?
【发布时间】:2014-08-06 09:13:47
【问题描述】:

编辑: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 行的情况下运行时,您会得到以下结果:

正如预期的那样,第一个容器 1 被渲染(带有黄色和红色方块),在顶部容器 2 被渲染(带有蓝色方块),所以红色方块被隐藏了。 在黄色“边框”内点击时,输出为yellow hit,在蓝色方格内点击会打印blue hit,一切正常。

然而,当 zPosition 行被插入时,您会得到以下信息:

如您所见,container2 的蓝色方块与 container1 的两个方块交错,但是当您在红色方块内单击时,您会得到blue hit!
在确定哪个节点最适合触摸时,container2 中的所有内容仍位于 container1 之上。

这是预期的行为吗?如果是这样,有没有一种通用的方法可以在不失去理智的情况下处理这个问题?

【问题讨论】:

    标签: ios sprite-kit hittest zposition


    【解决方案1】:

    我不知道自您的帖子以来是否有任何变化,或者您是否做错了什么,但就我而言,它确实有效。

    我只是将您的代码复制粘贴到一个新项目中并进行测试。

    如果红色方块在顶部,我会得到红色,如果蓝色方块在顶部,我会得到蓝色方块。

    【讨论】:

    • 我在 iOS 8.3 中重新测试了这个,你是对的,它已经修复了。我在 iOS 7.1.2 设备上重新运行了相同的项目,当显示红色方块时它仍然显示“蓝色命中”,因此它只能在不运行 iOS7 的任何设备上正常工作。感谢您查看
    【解决方案2】:

    是的,这是预期的行为。绘图和触摸的 z 位置不相同。虽然有类似全局 z 位置的东西,用于绘制用于确定哪个节点被触摸的位置是相对于父节点的(以及它们彼此之间的 z 关系)。

    【讨论】:

    • 这并没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方发表评论 - 您可以随时评论自己的帖子,一旦您有足够的reputation,您就可以comment on any post。
    • 你有任何来源这是预期的行为吗?将点击红色方块解释为点击蓝色方块感觉非常奇怪和不直观
    • @chopper:很抱歉以错误的方式使用系统。我应该对原始帖子发表评论,并且没有提供没有答案的答案。 Pieter:我在自己的项目中经过数小时的反复试验后发现了这一点。是的,这是违反直觉的。我认为这样做的唯一原因是,当您开始使用不同类型的 SKNodes(如 SKEffectNodes 和 SKCropNodes)时,让“touch z-order”与“draw z-order”不同可能是有意义的。但这只是猜测而不是知识。
    猜你喜欢
    • 2016-01-31
    • 1970-01-01
    • 2021-11-07
    • 1970-01-01
    • 2023-03-13
    • 2014-10-08
    • 2021-05-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多