SKShapeNode没有响应PhysicsBody。

4

我创建了一个SKShapeNode并给它分配了一个physicsBody。但是,当有接触时它并没有被触发。

SKShapeNode的创建代码如下:

-(SKShapeNode*)gravityline{
    //SKSpriteNode *lolo=[[SKSpriteNode alloc]init];
    SKShapeNode *lolo = [[SKShapeNode alloc] init];
    CGPoint fff=CGPointMake(ray1.position.x, ray1.position.y);
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, fff.x, fff.y);
    CGPathAddLineToPoint(path, 0,rayoriginpoint.x,rayoriginpoint.y );
    CGPathCloseSubpath(path);
    lolo.path = path;
    lolo.name=@"gravityline";
    lolo.strokeColor=[SKColor greenColor];
    lolo.glowWidth=.1;
    CGPathRelease(path);
    lolo.physicsBody=[SKPhysicsBody bodyWithEdgeFromPoint:fff toPoint:rayoriginpoint];
    //lolo.physicsBody=[SKPhysicsBody bodyWithEdgeLoopFromPath:path];
    //lolo.physicsBody=[SKPhysicsBody bodyWithPolygonFromPath:path];
    lolo.physicsBody.categoryBitMask=raylightCategory;
    lolo.physicsBody.collisionBitMask=batCategory;
    lolo.physicsBody.contactTestBitMask=batCategory;
    lolo.physicsBody.usesPreciseCollisionDetection=YES;
    lolo.physicsBody.linearDamping=0;
    lolo.physicsBody.restitution=1.0;
    lolo.physicsBody.dynamic=NO;

    return lolo;
}

这是触发代码:
- (void)didBeginContact:(SKPhysicsContact *)contact
{
    SKPhysicsBody *firstBody, *secondBody;
    if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
    {
        firstBody = contact.bodyA;
        secondBody = contact.bodyB;
    }
    else
    {
        firstBody = contact.bodyB;
        secondBody = contact.bodyA;
    }
    if (firstBody.categoryBitMask == raylightCategory && secondBody.categoryBitMask==batCategory)
    {
        NSLog(@"Contact with bat have been made");
        [secondBody.node removeFromParent];
    }
}

如果有人知道我做错了什么,为什么SKShapeNode没有激活物理引擎,请告诉我。

你好,这里有同样的问题。你解决了吗? - Doug
不,我将其声明为SKSpriteNode而不是SKShapeNode。 - TALAA
请尝试在实际设备上进行测试。模拟器可能会出现skhapenodes问题。 - 4GetFullOf
2个回答

0

你的代码似乎没有展示出"gravityLine"正在与什么物体发生碰撞。从描述中我只能猜测它没有检测到与一个圆形物体(如球和球棒)的碰撞。

"gravityLine"方法似乎返回了一个由边缘形状定义的SKShapeNode:

lolo.physicsBody=[SKPhysicsBody bodyWithEdgeFromPoint:fff toPoint:rayoriginpoint];

在处理碰撞时,重要的是要阅读苹果公司的Sprite Kit编程指南,特别是它对三种形状的解释。

1)动态体模拟具有体积和质量的物理对象,可以受到系统中的力和碰撞的影响。使用动态体来表示场景中需要移动并相互碰撞的物品。
2)静态体类似于动态体,但其速度被忽略,并且不受力或碰撞的影响。然而,由于它仍然具有体积,其他物体可以从其上弹开或与其交互。使用静态体来表示占据场景空间但不应被模拟移动的物品。例如,您可以使用静态体来表示迷宫的墙壁。 虽然将静态体和动态体视为不同的实体很有用,但在实践中,这些是可以应用于任何基于体积的物理体的两种不同模式。这很有用,因为您可以选择性地启用或禁用体的效果。
3)边缘是一种静态无体积的物体。边缘永远不会被模拟移动,它们的质量也不重要。边缘用于表示场景内的负空间(例如另一个实体内部的空洞)或不可穿越的隐形薄边界。例如,边缘经常用于表示场景的边界。 边缘和体积之间的主要区别在于边缘允许在其自身边界内移动,而体积被认为是实体物体。如果通过其他方式移动边缘,则它们只与体积交互,而不与其他边缘交互。 基于上述信息,如果您阅读使用了bodyWithEdgeFromPoint:toPoint:方法的文档,您将会发现您正在创建一个“基于边缘”的物理体。

返回值

一个新的基于边缘的物理体。

讨论

边缘没有体积或质量,并且始终被视为动态属性等于NO。边缘只能与基于体积的物理体碰撞。

为了使您的碰撞起作用,您必须确保您的边缘与基于体积的物理体发生碰撞。每个物理体形状创建方法都记录了它正在创建的形状类型。
如果您正在使用与您的边缘发生碰撞的基于体积的物理体,则另一个可能性可能是涉及对象的大小或速度。再次阅读苹果公司的文档可以澄清这一点。 为小型或快速移动的对象指定高精度碰撞: 当Sprite Kit执行碰撞检测时,它首先确定场景中所有物理体的位置。然后它确定是否发生了碰撞或接触。这种计算方法很快,但有时会导致漏掉碰撞。一个小的物体可能移动得如此之快,以至于它完全穿过另一个物理体,而从未有两个物体接触的动画帧。

如果您有必须碰撞的物理体,则可以提示Sprite Kit使用更精确的碰撞模型来检查交互。这个模型更昂贵,因此应该谨慎使用。当任一物体使用精确碰撞时,将联系并测试多个运动位置,以确保检测到所有接触。

ship.physicsBody.usesPreciseCollisionDetection = YES;

其他可能性也会导致碰撞出现问题,比如为分配给物理体的路径提供错误的位置信息。重要的是要理解,当您将路径设置为节点时,形状是使用节点的本地坐标系设置的。请记住,Sprite Kit 中的原点位于左下角(而不是 UIKit 的左上角),当您将路径分配给节点的物理体时,该路径相对于节点的锚点放置。

例如:

SKShapeNode *ball = [[SKShapeNode alloc] init];
CGRect ballFrame = CGRectMake(-25.0, -25.0, 50.0, 50.0);
[ball setPath:[UIBezierPath bezierPathWithOvalInRect:ballFrame].CGPath];
[ball setPosition:CGPointMake(100.0, 450.0)];
[ball setFillColor:[UIColor redColor]];
[ball setPhysicsBody:[SKPhysicsBody bodyWithCircleOfRadius:25.0]];

如果我将“ballFrame”的原点设置为(0,0),那么半径为25.0的物理体的圆形将不会与球的形状重合,因为物理体的左下角将放置在球的锚点处,该锚点位于球的本地坐标系中的x = 0和y = 0点。

0

这肯定行不通:

lolo.physicsBody=[SKPhysicsBody bodyWithEdgeFromPoint:fff toPoint:rayoriginpoint];

如果有任何问题,这将返回一个已分配给其他节点的主体。但我想它只会返回nil。

这条注释行也不起作用:

//lolo.physicsBody=[SKPhysicsBody bodyWithEdgeLoopFromPath:path];

边缘形状将创建静态(即:不可移动)的物体。因此,该节点不会通过物理运动,并且如果我没有弄错的话,您也不会从与静态物体接触中获得接触响应,只有动态物体。

这个应该可以工作:

//lolo.physicsBody=[SKPhysicsBody bodyWithPolygonFromPath:path];

但是这里你将body设置为静态的:

lolo.physicsBody.dynamic=NO;

因此,如果您要创建具有边循环的主体,则适用相同的规则。

1
正如您所看到的,它也不起作用,无论是将dynamic设置为YES还是NO,都没有任何作用。 - TALAA
使用类似的方法,我无法检测到碰撞。就好像物理体与SKShapeNode不起作用一样。有没有更进一步的建议? - Doug

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接