一尘不染

crashBitMask如何工作?Swift / SpriteKit

swift

据我所知,物理物体的默认设置是当它们相互碰撞时会相互反弹,直到将其rashingBitMask设置为相等的数值为止。

但是,由于我相信的碰撞位掩码,完成一个看起来应该非常简单的工作时遇到了很大的问题。

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个球和边框。我可以得到想要的碰撞检测,但是当我添加边框的类别位掩码时,它允许球既通过屏幕又通过屏幕,这是我所不希望的。

我也希望球彼此弹起,但是只有当我注释掉球的categoryBitMask之一时,它们才会弹起。否则,他们会互相经历。

这对我来说绝对没有意义,因为这些项目中的每一个都有不同的碰撞位掩码。有时,将所有数字都设置为5会使所有内容相互通过,但是将其全部设置为6则所有内容都可以相互碰撞。

碰撞位掩码的工作原理如何?是否有适当的方法来管理许多交叉碰撞规则?


阅读 237

收藏
2020-07-07

共1个答案

一尘不染

由于未正确设置类别,联系人和冲突位掩码,因此无法获得所需的行为。这是关于如何设置它的示例:

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对象,并将其传递给物理世界的委托。为了获得最佳性能,请仅在联系人掩码中设置感兴趣的交互的位。

flictionBitmask-一个掩码,定义可以与该物理物体碰撞的物理物体类别。

当两个物理物体相互接触时,可能会发生碰撞。通过执行逻辑“与”运算,将该人体的防撞蒙版与其他人体的类别蒙版进行比较。如果结果为非零值,则此主体受碰撞影响。每个机构独立选择是否要受到另一个机构的影响。例如,您可以使用它来避免碰撞计算,该碰撞计算对物体速度的变化可以忽略不计。

因此,基本上,要设置所有这些内容,您应该问自己以下问题:

好的,我有一个绿色的球,一个红色的球和场景中的墙对象。我希望在哪个主体之间发生冲突,或者何时要注册联系人?我希望一个绿色和红色的球相互碰撞并碰撞到墙壁。没问题
我将首先正确设置类别,然后设置冲突位掩码,如下所示:

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

希望这个对你有帮助。

2020-07-07