Как работает collisionBitMask? Swift/SpriteKit

Насколько я знаю, по умолчанию для физических тел следует отскакивать друг от друга, когда они попадают друг в друга, пока вы не установите их collisionBitMask равным числом.

Тем не менее, у меня возникла огромная проблема с тем, что кажется, что это должно быть очень просто из-за столкновенияBitmasks, которое я считаю.

    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 мяча и мое пограничное тело. Я могу получить обнаружение столкновения, которое я хочу, но когда я добавляю битовую маску категории пограничного тела, он позволяет шарам как проходить, так и выключать экран, который я не хочу.

Я также хочу, чтобы мячи отскакивали друг от друга, но только когда я прокомментирую одну из мячей categoryBitMasks, они отскакивают. В противном случае они проходят друг к другу.

Это не имеет никакого смысла для меня, потому что у каждого из этих предметов есть другая collisionbitmask. У меня также было это иногда, когда установка всех чисел, равных 5, позволяла бы всем проходить друг через друга, но тогда установка всего на 6 позволила бы всем ударить друг друга.

Как точно работают битмаксы столкновений и есть ли способ управлять множеством перекрещивающихся правил столкновений?

Ответы

Ответ 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 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 - Маска, определяющая, какие категории тел вызывают уведомления о пересечении с текущим физическим телом.

Когда два тела имеют одинаковое пространство, каждая маска категории bodys протестированы против другой контактной маски bodys, выполнив логическую И операция. Если либо сравнение приводит к ненулевому значению, Объект SKPhysicsContact создается и передается в мир физики делегировать. Для достижения наилучшей производительности только установите бит в маске контактов для взаимодействий, которые вас интересуют.

collisionBitmask - Маска, которая определяет, какие категории физических тел могут столкнуться с этим физическим телом.

Когда два физических тела контактируют друг с другом, может произойти столкновение. Эта маска столкновения bodys сравнивается с другой категорией bodys маски, выполняя логическую операцию И. Если результат отличен от нуля значение, на это тело влияет столкновение. Каждый орган независимо выбирает, хочет ли он быть затронутым другим телом. Для Например, вы можете использовать это, чтобы избежать вычислений столкновений, которые делают незначительные изменения скорости bodys.

Итак, в основном, чтобы настроить все это, вы должны спросить себя:

Хорошо, у меня есть зеленый шар, красный шар и предметы на стене. Между телами я хочу, чтобы произошли столкновения, или когда я хочу зарегистрировать контакты? Я хочу, чтобы зеленый и красный шар сталкивались друг с другом и сталкивались с стенами. Не проблема. Сначала я правильно настрою категории, а затем поставлю такие бит-бит:

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

wall.collisionBitMask = GreenBall | RedBall

Теперь я хочу обнаружить, когда происходят некоторые контакты (в didBeginContact: method)... Но я не хочу получать уведомления обо всех возможных контактах, а скорее получать уведомления о контактах между шарами (контакты между шарами и стеной будет проигнорировано). Поэтому давайте установим contactTestBitMasks для достижения этой цели:

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

И что это. Важно, когда вы не используете обнаружение контактов, вы не должны устанавливать contactTestBitMask. Это связано с соображениями производительности. Если вам не требуется обнаружение столкновений, и вас интересует только обнаружение контактов, вы можете установить collisionBitMask = 0.

Важно:

Удостоверьтесь, что вы установили делегат физического мира, чтобы использовать методы didBeginContact и didEndContact:

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

Надеюсь, это немного поможет.