Как работает collisionBitMask? Swift/SpriteKit
насколько мне известно, по умолчанию для физических тел отскакивают друг от друга, когда они ударяют друг друга, пока вы не установите их collisionBitMask равным числом.
однако у меня огромная проблема с выполнением того, что кажется очень простым из-за collisionBitmasks, я считаю.
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 шара и мое тело границы. Я могу получить обнаружение столкновений, которое я хочу, но когда я добавляю битовую маску категории тела границы, это позволяет мячи проходят через экран и исчезают с него, чего я не хочу.
Я также хочу, чтобы шары отскакивали друг от друга, но только когда я комментирую одну из масок categorybit мяча, они отскакивают. Иначе они проходят друг через друга.
Это не имеет абсолютно никакого смысла для меня, потому что каждый из этих элементов имеет другую маску collisionbit. У меня также было это иногда, когда установка всех чисел, равных 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'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
: метод)... Но я не хочу получать уведомления обо всех возможных контактах, а скорее получать уведомления только о контактах между шарами (контакты между шарами и стеной будут игнорироваться). Так что давайте set contactTestBitMasks
для достижения этого:
greenBall.contactTestBitMask = GreenBallCategory | RedBallCategory;
redBall.contactTestBitMask = GreenBallCategory | RedBallCategory;
и это все. Важно, когда вы не используете обнаружение контактов, вы не должны устанавливать contactTestBitMask
. Это из-за причин производительности. Если вам не нужно обнаружение столкновений, и вы заинтересованы только в обнаружении контактов, вы можете установить collisionBitMask = 0
.
важно:
убедитесь, что вы установили контактный делегат мира физики для использования didBeginContact
и didEndContact
методы:
self.physicsWorld.contactDelegate = self; //where self is a current scene
надеюсь, это немного поможет.