当前位置: 首页 > 知识库问答 >
问题:

collisionBitMask是如何工作的?Swift/SpriteKit

彭鸿文
2023-03-14

据我所知,物理体的默认方法是在相互撞击时相互反弹,直到您将它们的碰撞BitMask设置为相等的数量。

然而,我有一个巨大的问题,完成看起来应该很简单的事情,因为我相信冲突位掩码。

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

这里我有两个球和边界体。我可以得到我想要的碰撞检测,但当我添加边界体的类别位掩码时,它允许球穿过和离开屏幕,这是我不想要的。

我也希望球相互反弹,但只有当我注释掉球的一个类别BitMask时,它们才会反弹。否则,它们会相互经历。

这对我来说毫无意义,因为每个项目都有不同的碰撞位掩码。我也有过这样的情况,将所有数字设置为5将允许所有内容相互传递,但将所有内容设置为6则允许所有内容互相碰撞。

碰撞位掩码到底是如何工作的?是否有适当的方法来管理大量交叉碰撞规则?

共有2个答案

胡景澄
2023-03-14

只是想在这里添加一些东西,如果接触或碰撞无法正常工作,则需要确保在应用位掩码之前先分配物理实体形状。

位掩码不工作的示例:

        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];

无论如何,可能只是一个新手的错误,但我会在这里分享,因为这是导致我的不能正常工作。

孔茂
2023-03-14

您无法获得所需的行为,因为您没有正确设置类别,接触和碰撞位掩码。下面是如何设置其工作的示例:

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和contactTestBitMaskproperties,您可以定义哪些物理体彼此交互,以及何时通知游戏这些交互。

ContactTestBitMask-一个掩码,它定义了哪些类别的主体会导致与当前物理主体的交集通知。

当两个主体共享同一空间时,通过执行逻辑 AND 运算,针对另一个主体的接触面罩测试每个主体的类别掩模。如果任一比较产生非零值,则会创建一个 SK 物理接触对象并将其传递给物理世界的委托。为了获得最佳性能,请仅在联系人掩码中为您感兴趣的交互设置位。

碰撞位掩码-定义哪类物理体可以与此物理体碰撞的掩码。

当两个物理实体相互接触时,可能会发生碰撞。通过执行逻辑“与”运算,将该几何体的碰撞遮罩与另一个几何体的类别遮罩进行比较。如果结果是非零的值,这个物体会受到碰撞的影响。每个身体独立地选择它是否想要被另一个身体影响。例如,您可以使用该选项来避免碰撞计算,碰撞计算对物体速度的影响可以忽略不计。

所以基本上,要设置所有这些,你应该问自己一些事情:

好的,我有一个绿色的球,和一个红色的球,还有现场的墙壁物体。我希望在哪个物体之间发生碰撞,或者当我想注册联系人时?我希望一个绿色和一个红色的球相互碰撞,碰撞到墙壁上。这不是问题。我将首先正确设置类别,然后我将设置碰撞位蒙版,如下所示:

greenBall.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory; //greenBall will collide with greenBall, redBall and a wall
redBall.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory

wall.collisionBitMask = GreenBall | RedBall

现在,我想检测一些联系人何时出现(在didBEINContent: method中)…但是我不想收到所有可能的联系人的通知,而是只收到球之间的联系人的通知(球和墙之间的联系人将被忽略)。所以让我们设置contactTestBitMask来实现这一点:

greenBall.contactTestBitMask = GreenBallCategory | RedBallCategory;
redBall.contactTestBitMask = GreenBallCategory | RedBallCategory;

仅此而已。重要的是,当您不使用接触检测时,您不应该设置< code>contactTestBitMask。这是因为性能原因。如果不需要碰撞检测,并且只对检测接触感兴趣,可以设置< code>collisionBitMask = 0。

重要:

确保您已经设置了physics world的联系人代理,以便使用< code>didBeginContact和< code > didentcontact 方法:

self.physicsWorld.contactDelegate = self; //where self is a current scene

希望这会有所帮助。

 类似资料:
  • 问题内容: 据我所知,物理物体的默认设置是当它们相互碰撞时会相互反弹,直到将其rashingBitMask设置为相等的数值为止。 但是,由于我相信的碰撞位掩码,完成一个看起来应该非常简单的工作时遇到了很大的问题。 所以在这里,我有2个球和边框。我可以得到想要的碰撞检测,但是当我添加边框的类别位掩码时,它允许球既通过屏幕又通过屏幕,这是我所不希望的。 我也希望球彼此弹起,但是只有当我注释掉球的cat

  • 应用程序具有上下文路径-->/spring-form-simple-project 因此,为了访问,我使用: 这个控制器又返回student.jsp,当提交这个student.jsp时,它用-->@RequestMapping(value=“/AddStudent”,method=RequestMethod.post)调用controller 任何关于这通常如何工作的指示都将是有帮助的。 谢谢!

  • 问题内容: 我正在使用 shouldChangeCharactersInRange 作为使用即时类型搜索的方式。 但是我有一个问题,在文本字段实际更新之前 应该 调用 shouldChangeCharactersInRange : 在目标C中,我使用以下方法解决了这个问题: 但是,我尝试用Swift编写此代码: 在获得值之前,该方法仍会被调用? 问题答案: 雨燕4,雨燕5 此方法不使用 注意。使用

  • 本文向大家介绍hibernate 是如何工作的?相关面试题,主要包含被问及hibernate 是如何工作的?时的应答技巧和注意事项,需要的朋友参考一下 读取并解析配置文件。 读取并解析映射文件,创建 SessionFactory。 打开 Session。 创建事务。 进行持久化操作。 提交事务。 关闭 Session。 关闭 SessionFactory。

  • 我很想知道谷歌应用商店服务中的Activity认可是如何工作的? 我认为活动是通过加速计数据识别的。是这样吗?。请告诉我详细情况如何

  • 我对GridBagLayout这一主题不熟悉,我无法理解约束、重量和填充之间的确切区别。 我可以而不分配。 除非您指定了至少一个非零值,否则所有组件都会聚集在其容器的中心。这是因为当权重为0.0(默认值)时,GridBagLayout会在其单元格网格和容器边缘之间放置任何额外的空间。 我的问题是,如果这是真的,那么为什么组件之间没有空间,它们看起来是连接的?