Ответ 1
Существует много документации по этим темам, но вот практический пример.
Сила категорииBitMasks
Представьте, что у вас есть коллекция из трех узлов pool
, basketball
и bowlingball
. Теперь, очевидно, мы хотим, чтобы теги basketball
и bowlingball
сталкивались друг с другом. Таким образом, вы устанавливаете collisionBitMasks следующим образом:
basketball.physicsBody?.collisionBitMask = UInt32(2)
bowlingball.physicsBody?.collisionBitMask = UInt32(2)
Великий. Теперь мы хотим, чтобы bowlingball
опустился до нижней части pool
, а basketball
столкнулся с pool
(может быть, больше всплеск, но нести со мной). Как мы это сделаем? Мы могли бы попробовать:
pool.physicsBody?.collisionBitMask = UInt32(2) // ?
Но подождите, это приведет к тому, что basketball
И bowlingball
столкнется с pool
. Мы хотим, чтобы basketball
сталкивался с пулом, тогда как мы хотим, чтобы bowlingball
игнорировал pool
и погружался прямо вниз, без столкновений. Здесь categoryBitMask
пригодится:
let basketballBitMask = UInt32(1)
let bowlingballBitMask = UInt32(2)
let poolBitMask = UInt32(4) // Why 4? See next section
basketball.physicsBody?.categoryBitMask = basketballBitMask
bowlingball.physicsBody?.categoryBitMask = bowlingballBitMask
pool.physicsBody?.categoryBitMask = poolBitMask
Поскольку каждому объекту присваивается уникальный номер, вы можете выбрать, с какими объектами вы хотите столкнуться с другим объектом:
// basketball physics body collides with bowlingball(2) OR pool(4)
basketball.physicsBody?.collisionBitMask = bowlingballBitMask | poolBitMask
// ( '|' = logical OR operator)
// bowlingball physics body only collides with basketball(1)
bowlingball.physicsBody?.collisionBitMask = basketballBitMask
// pool physics body only collides with basketball(1)
pool.physicsBody?.collisionBitMask = basketballBitmask
Если вы не уверены, что странное '|' символ, я настоятельно рекомендую оперативную документацию для продвинутых операторов, чтобы помочь вам понять, что происходит здесь.
Почему бы просто не использовать collisionBitMasks?
Итак, мы установили несколько бит-масок. Но как они используются? Если у нас есть только два объекта, почему мы не можем просто сравнить collisionBitMasks?
Проще говоря, это просто не так, как это работает. Когда a bowlingball
входит в контакт с pool
, физический движок SpriteKit будет И ('&') вместе bowlingball
categoryBitMask с pool
collisionBitMask (или наоборот; результат тот же):
objectsShouldCollide = (bowlingball.physicsBody?.categoryBitMask &
pool.physicsBody?.collisionBitMask)
// objectsShouldCollide = (ob010 & 0b100) = 0b000
Так как bowlingball
categoryBitMask
и pool
collisionBitMask
имеют нулевые биты, то objectsShouldCollide
равно нулю, а SpriteKit останавливает объекты от столкновения.
Но в вашем случае вы не устанавливаете свои объекты categoryBitMask
s. Таким образом, они имеют значение по умолчанию 2 ^ 32 или 0xFFFFFFFF (шестнадцатеричное представление) или в двоичном формате, 0b1111111111111111111111111111111111. Поэтому, когда "объект" попадает в "второй" объект, SpriteKit делает это:
objectsShouldCollide = (0b11111111111111111111111111111111 & // Default categoryBitMask for "object"
0b00000000000000000000000000000001) // collisionBitMask for "second" object
// = 0b00000000000000000000000000000001
Итак, если вы не определили object
categoryBitMask, независимо от того, что вы установили как объект second
collisionBitMask
, объектыShouldCollide никогда не будут равны нулю, и они всегда будут сталкиваться.
Примечание: вы можете установить для объекта collisionBitMask
значение 0; но тогда этот объект никогда не сможет столкнуться ни с чем.
Использование степеней 2 (0,1,2,4,8 и т.д.) для категорииBitMasks
Теперь предположим, что мы хотели включить несколько bowlingball
, которые столкнулись друг с другом. Легко:
bowlingball.physicsBody?.collisionBitMask = basketballBitMask | bowlingballBitMask
// bowlingball collision bit mask (in binary) = 0b10 | 0b01 = 0b11
// bowlingball collision bit mask (in decimal) = 2 | 1 = 3
Здесь вы можете видеть, что если бы мы установили pool
physicalCategory в UInt32 (3), это уже не могло бы отличаться от bowlingball
или basketball
.
Дополнительные предложения
Научитесь имя переменным с целью, даже если вы просто используете их для тестирования (хотя, по совпадению, "object
и second
объект" работал достаточно хорошо".
Используйте структуру для битмаски, чтобы упростить код и улучшить читаемость:
struct PhysicsCategory {
static let Obj1 : UInt32 = 0b1 << 0
static let Obj2 : UInt32 = 0b1 << 1
static let Obj3 : UInt32 = 0b1 << 2
static let Obj4 : UInt32 = 0b1 << 3
}
obj1.physicsBody?.categoryBitmask = PhysicsCategory.Obj1 // etc