碰撞位掩码是如何工作的?斯威夫特/雪碧套件 [英] How does collisionBitMask work? Swift/SpriteKit

查看:13
本文介绍了碰撞位掩码是如何工作的?斯威夫特/雪碧套件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,Physics 物体的默认设置是在它们相互碰撞时相互反弹,直到您将它们的 collisionBitMask 设置为相等的数字.

As far as I'm aware the default for Physics bodies is to bounce off each other when they hit each other until you set their collisionBitMask to an equal number.

但是,由于我相信碰撞位掩码,我在完成看起来应该非常简单的事情时遇到了一个巨大的问题.

However, I'm having a huge issue accomplishing what seems like it should be very simple because of collisionBitmasks I believe.

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 个球和我的边框.我可以得到我想要的碰撞检测,但是当我添加边框体的类别位掩码时,它允许球穿过和离开屏幕,这是我不想要的.

So here I've got my 2 balls and my border body. I can get collision detection which I want, but when I add the border body's category bit mask, it allows the balls to both go through and off the screen, which I don't want.

我还希望球相互反弹,但只有当我注释掉其中一个球的 categoryBitMask 时,它们才会反弹.否则它们会互相穿过.

I also want the balls to bounce off each other, but only when I comment out one of the ball's categoryBitMasks do they bounce. Otherwise they go through each other.

这对我来说完全没有意义,因为这些项目中的每一个都有不同的碰撞位掩码.有时我也有这样的情况,将所有数字设置为 5 将允许所有内容相互通过,但将其全部设置为 6 将允许所有内容相互碰撞.

That makes absolutely no sense to me because each of these items has a different collisionbitmask. I also had it sometimes where setting all the numbers equal to 5 would allow everything to pass through each other, but then setting it all to 6 would allow everything to hit each other.

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

How exactly do collision bitmasks work and is there a proper way to manage a lot of crisscrossing collision rules?

推荐答案

您无法获得所需的行为,因为您没有正确设置类别、接触和碰撞位掩码.这是一个关于如何设置它的示例:

You can't get desired behaviour because you haven't set category, contact and collision bit masks properly. Here is an example on how you can set this to work:

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 这是一个掩码,用于定义物理体所属的类别:

I would recommend you to read docs about categoryBitMask which is a mask that defines which categories a physics body belongs to:

场景中的每个物理体最多可以分配给 32 个不同的类别,每个对应于位掩码中的一个位.你定义游戏中使用的掩码值.与collisionBitMask 和 contactTestBitMask 属性,您定义哪个物理实体相互交互以及何时通知您的游戏这些互动.

Every physics body in a scene can be assigned to up to 32 different categories, each corresponding to a bit in the bit mask. You define the mask values used in your game. In conjunction with the collisionBitMask and contactTestBitMask properties, you define which physics bodies interact with each other and when your game is notified of these interactions.

contactTestBitMask -一个掩码,它定义了哪些类别的物体会导致与当前物理物体的交叉通知.

contactTestBitMask - A mask that defines which categories of bodies cause intersection notifications with a current physics body.

当两个 body 共享同一个空间时,每个 body 的类别掩码为通过执行逻辑测试对另一个身体的接触面罩与操作.如果任一比较结果为非零值,则SKPhysicsContact 对象被创建并传递给物理世界的代表.为获得最佳性能,仅在触点掩码中设置位您感兴趣的互动.

When two bodies share the same space, each body’s category mask is tested against the other body’s contact mask by performing a logical AND operation. If either comparison results in a nonzero value, an SKPhysicsContact object is created and passed to the physics world’s delegate. For best performance, only set bits in the contacts mask for interactions you are interested in.

collisionBitmask -定义哪些类别的物理体可以与此物理体发生碰撞的掩码.

collisionBitmask - A mask that defines which categories of physics bodies can collide with this physics body.

当两个物理体相互接触时,可能会发生碰撞.将此主体的碰撞掩码与其他主体的类别进行比较通过执行逻辑与运算来屏蔽.如果结果是非零值,这个物体会受到碰撞的影响.每个身体独立选择是否要被对方影响.为了例如,您可以使用它来避免碰撞计算对身体的速度进行微不足道的变化.

When two physics bodies contact each other, a collision may occur. This body’s collision mask is compared to the other body’s category mask by performing a logical AND operation. If the result is a nonzero value, this body is affected by the collision. Each body independently chooses whether it wants to be affected by the other body. For example, you might use this to avoid collision calculations that would make negligible changes to a body’s velocity.

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

So basically, to set up all these, you should ask your self something like:

好的,我有一个绿色球,一个红色球,以及场景中的墙壁对象.我希望在哪些物体之间发生碰撞,或者何时注册联系人?我想要一个绿色和一个红色的球相互碰撞并撞到墙上.不是问题.我将首先正确设置类别,然后我将设置这样的碰撞位掩码:

Okay, I have a green ball, and a red ball , and wall objects on the scene. Between which bodies I want collisions to occur, or when I want to register contacts? I want a green and a red ball to collide with each other and to collide against the walls. Not a problem. I will first set up categories properly, and then I will set collision bit masks like this:

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 来实现:

Now, I want to detect when some contacts occur (in didBeginContact: method)... But I don't want to get notified about all possible contacts, but rather to be notified just about contacts between balls (contacts between balls and a wall will be ignored). So lets set contactTestBitMasks to achieve this:

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

就是这样.重要的是当你不使用接触检测时,你不应该设置contactTestBitMask.这是因为性能原因.如果不需要碰撞检测,只对检测接触感兴趣,可以设置collisionBitMask = 0.

And that's it. The important thing is when you not using contact detection, you should not set contactTestBitMask. This is because of performance reasons. If you don't need collision detection, and you are interested only in detecting contacts, you can set collisionBitMask = 0.

重要:

确保您已设置物理世界的联系人委托,以便使用 didBeginContactdidEndContact 方法:

Make sure you have set physics world's contact delegate in order to use didBeginContact and didEndContact methods:

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

希望这会有所帮助.

这篇关于碰撞位掩码是如何工作的?斯威夫特/雪碧套件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆