据我所知,物理体的默认值是相互反弹,直到你将collisionBitMask设置为相等的数字为止。
但是,我遇到了一个很大的问题,因为我相信的碰撞比特看起来应该很简单。
let RedBallCategory : UInt32 = 0x1 << 1
let GreenBallCategory: UInt32 = 0x1 << 2
let RedBarCategory : UInt32 = 0x1 << 3
let GreenBarCategory : UInt32 = 0x1 << 4
let WallCategory : UInt32 = 0x1 << 5
greenBall.physicsBody?.categoryBitMask = GreenBallCategory
greenBall.physicsBody?.contactTestBitMask = RedBarCategory
greenBall.physicsBody?.collisionBitMask = GreenHealthCategory
redBall.physicsBody?.categoryBitMask = RedBallCategory
redBall.physicsBody?.contactTestBitMask = GreenBarCategory
redBall.physicsBody?.collisionBitMask = RedHealthCategory
let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody = borderBody
self.physicsBody?.friction = 0
borderBody.contactTestBitMask = RedBallCategory | GreenBallCategory
borderBody.categoryBitMask = WallCategory
所以在这里我有2个球和我的边界身体。我可以得到我想要的碰撞检测,但是当我添加边框体的类别位掩码时,它允许球通过和离开屏幕,这是我不想要的。
我也希望球能够相互反弹,但只有当我注意到其中一个球的类别时,他们才能反弹。否则他们会互相通过。
这对我来说完全没有意义,因为每个项目都有不同的碰撞比特。我也有时将所有数字设置为5将允许所有数据相互通过,但是将其全部设置为6将允许所有内容相互碰撞。
碰撞位掩码究竟是如何工作的,是否有适当的方法来管理大量交叉碰撞规则?
答案 0 :(得分:47)
您无法获得所需的行为,因为您尚未正确设置类别,接触和碰撞位掩码。以下是如何设置此功能的示例:
greenBall.physicsBody?.categoryBitMask = GreenBallCategory //Category is GreenBall
greenBall.physicsBody?.contactTestBitMask = RedBarCategory | WallCategory //Contact will be detected when GreenBall make a contact with RedBar or a Wall (assuming that redBar's masks are already properly set)
greenBall.physicsBody?.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory //Collision will occur when GreenBall hits GreenBall, RedBall or hits a Wall
redBall.physicsBody?.categoryBitMask = RedBallCategory //Category is RedBall
redBall.physicsBody?.contactTestBitMask = GreenBarCategory | GreenBallCategory | WallCategory //Contact will be detected when RedBall make a contact with GreenBar , GreenBall or a Wall
redBall.physicsBody?.collisionBitMask = RedBallCategory | GreenBallCategory | WallCategory //Collision will occur when RedBall meets RedBall, GreenBall or hits a Wall
let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody = borderBody
self.physicsBody?.friction = 0
borderBody.contactTestBitMask = RedBallCategory | GreenBallCategory //Contact will be detected when red or green ball hit the wall
borderBody.categoryBitMask = WallCategory
borderBody.collisionBitMask = RedBallCategory | GreenBallCategory // Collisions between RedBall GreenBall and a Wall will be detected
我建议你阅读有关categoryBitMask的文档,这是一个定义物理机构所属类别的掩码:
场景中的每个物理主体最多可分配32个不同的物理主体 类别,每个类别对应于位掩码中的一个位。你定义 游戏中使用的蒙版值。与...结合 collisionBitMask和contactTestBitMask属性,你定义哪个 物理机构互相交流,当你的游戏得到通知时 这些互动。
contactTestBitMask - 一个掩码,用于定义哪些类别的物体会导致与当前物理体的交集通知。
当两个物体共享相同的空间时,每个物体的类别掩码都是 通过执行逻辑来测试另一个身体的接触面罩 和操作。如果任一比较结果为非零值,则为 创建SKPhysicsContact对象并将其传递给物理世界 代表。为获得最佳性能,仅在触点掩码中设置位 您感兴趣的互动。
collisionBitmask - 一个掩码,用于定义哪些类别的物理实体可以与此物理实体发生碰撞。
当两个物理实体相互接触时,可能会发生碰撞。 该身体的碰撞面具与其他身体的类别进行比较 通过执行逻辑AND操作进行掩码。如果结果是非零 值,这个身体受到碰撞的影响。每个身体独立 选择是否想要受到其他身体的影响。对于 例如,您可以使用它来避免碰撞计算 对身体的速度做出微不足道的改变。
所以基本上,要设置所有这些,你应该问自己的东西:
好的,我有一个绿色的球,一个红色的球,还有一些墙上的物体。在哪些机构之间我想要发生碰撞,或者我想要注册联系人?我想要一个绿色和红色的球相互碰撞并碰撞墙壁。不是问题。我将首先正确设置类别,然后我将设置碰撞位掩码,如下所示:
greenBall.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory; //greenBall will collide with greenBall, redBall and a wall
redBall.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory
wall.collisionBitMask = GreenBall | RedBall
现在,我想检测一些联系人何时发生(didBeginContact
:方法)...但我不想收到有关所有可能联系人的通知,而是要通知球之间的联系(球和墙之间的接触将被忽略)。因此,设置contactTestBitMasks
来实现此目的:
greenBall.contactTestBitMask = GreenBallCategory | RedBallCategory;
redBall.contactTestBitMask = GreenBallCategory | RedBallCategory;
就是这样。重要的是,当您不使用接触检测时,不应设置contactTestBitMask
。这是因为性能原因。如果您不需要碰撞检测,并且只对检测联系人感兴趣,则可以设置collisionBitMask = 0
。
重要的:
确保您已设置物理世界的联系人委托,以便使用didBeginContact
和didEndContact
方法:
self.physicsWorld.contactDelegate = self; //where self is a current scene
希望这有点帮助。
答案 1 :(得分:1)
只需在此处添加一些内容,如果接触或碰撞无法正常工作,则需要确保在应用bitMask之前先分配PhysicalBody形状。
不起作用的位掩码的示例:
SKSpriteNode *bird = [SKSpriteNode spriteNodeWithImageNamed:@"bird1.png"];
bird.name = @"bird";
bird.physicsBody.categoryBitMask = birdCategory;
bird.physicsBody.contactTestBitMask = wallCategory | scoreCategory;
bird.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:bird.size.width/2.7];
bird.position = CGPointMake(_mySize.width/3.0, 2*_mySize.height/3.0);
[self addChild:bird];
工作一个:
SKSpriteNode *bird = [SKSpriteNode spriteNodeWithImageNamed:@"bird1.png"];
bird.name = @"bird";
bird.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:bird.size.width/2.7];
bird.physicsBody.categoryBitMask = birdCategory;
bird.physicsBody.contactTestBitMask = wallCategory | scoreCategory;
bird.position = CGPointMake(_mySize.width/3.0, 2*_mySize.height/3.0);
[self addChild:bird];
无论如何可能只是一个新手错误,但是我在这里分享,因为这是导致我无法正常工作的原因。