Предотвратить перекрытие между двумя SKPhysicBody одного и того же типа

У меня есть игра, в которой два мяча должны пройти через третий объект, выполняющий функцию финишной черты. Два мяча SKShapeNodes, финишная черта SKSpriteNode. Все они имеют прикрепленные к ним SKPhysicBodys с категориями, установленными следующим образом:

struct PhysicsCategory {
    static let ball: UInt32 = 0x1 << 1
    static let line: UInt32 = 0x1 << 2
}


ball.physicsBody = SKPhysicsBody(circleOfRadius: ballSize)
ball.physicsBody?.categoryBitMask = PhysicsCategory.ball
ball.physicsBody?.contactTestBitMask = PhysicsCategory.line
ball.physicsBody!.collisionBitMask = 1

line.physicsBody = SKPhysicsBody(rectangleOf: line.size)
line.physicsBody?.isDynamic = false
line.physicsBody?.categoryBitMask = PhysicsCategory.line
line.physicsBody?.contactTestBitMask = PhysicsCategory.ball
line.physicsBody!.collisionBitMask = 1

Поскольку я хочу, чтобы мячи могли пересекать финишную черту без столкновения, но при этом иметь возможность получать уведомления об этом, я установил collisionBitMask для мячей и линии на одно и то же значение.

Это дает мне результат, который я ищу. Однако похоже, что это имеет побочный эффект, заключающийся в том, что два шара также могут проходить друг через друга, чего не должно происходить.

Кроме того, если я установлю значение collisionBitMask на любое значение, отличное от 1, шары и линия натолкнутся друг на друга. Я прочитал документацию Apple по этому вопросу, но я думаю, что я что-то неправильно понял/пропустил.

Я предполагаю, что, поскольку оба шара видят друг друга с одним и тем же collisionBitMask. следует ожидать перекрытия. Чего я не понимаю, так это того, как этого избежать, не добавляя отдельную категорию для каждого шара.

Может кто-то указать мне верное направление? Как я могу сделать так, чтобы шары проходили через финишную черту, при этом не имея возможности перекрывать друг друга?


person Harold    schedule 13.11.2018    source источник


Ответы (1)


Я склонен время от времени путать это, но, надеюсь, я правильно это помню.

Если все, о чем вы заботитесь, это вернуть вызов столкновения на линии, которая в основном контролируется contactTestBitMask to ball, как у вас. Это то, что отправляет контакт в метод делегата. collisionBitMask управляет тем, что на самом деле управляет физическими вычислениями, то есть тем, что будет отражаться друг от друга.

По умолчанию collisionBitMask будет сталкиваться со всем, поэтому вы хотите указать только то, на чем вы хотите, чтобы он вычислял физику. У вас все установлено на 1, что не является чем-то конкретным в вашей сцене. Вот почему все проходит друг через друга. Я считаю, что 2 будет мячом, а 4 соответствует тому, что вы предоставили (если вы распечатаете PhysicsCategory.ball и PhysicsCategory.line, это то, что он выйдет из системы). Как правило, лучше всего использовать перечисления или структуры, которые вы создаете, вместо указания числа. С учетом сказанного я склонен использовать 0 ни за что.

Чтобы исправить это, вы хотите сообщить своим шарам, что вы хотите, чтобы они сталкивались с PhysicsCategory.ball, и вы хотите, чтобы ваша линия ни с чем не сталкивалась, поэтому вы хотите установить ее на 0.

struct PhysicsCategory {
    static let ball: UInt32 = 0x1 << 1
    static let line: UInt32 = 0x1 << 2
}


ball.physicsBody = SKPhysicsBody(circleOfRadius: ballSize)
ball.physicsBody?.categoryBitMask = PhysicsCategory.ball
ball.physicsBody?.contactTestBitMask = PhysicsCategory.line
ball.physicsBody!.collisionBitMask = PhysicsCategory.ball //changed to ball

line.physicsBody = SKPhysicsBody(rectangleOf: line.size)
line.physicsBody?.isDynamic = false
line.physicsBody?.categoryBitMask = PhysicsCategory.line
line.physicsBody?.contactTestBitMask = PhysicsCategory.ball
line.physicsBody!.collisionBitMask = 0 //you want no physics calculations
person Skyler Lauren    schedule 15.11.2018