SKPhysicsContact, когда объект сталкивается с более чем 1 объектом, обрабатывается первым, игнорирует все остальные... как?

Хорошо, у меня есть несколько физических объектов, и все они хорошо классифицированы, и мой didBeginContact правильно запущен и делает то, что должен делать. Проблема в следующем:

У меня есть две категории объектов, скажем, мяч и ракетка... Когда мяч касается ракетки, мяч должен взорваться... достаточно просто... Проблема заключается в том, что мяч может касаться двух ракеток одновременно... Таким образом, вызывается более одного didBeginContact, и поэтому происходит более 1 взрыва (по 1 на ракетку, с которой соприкасается мяч). Итак, проблема, которую я пытаюсь выяснить, заключается в том, как удалить/игнорировать все последующие контакты с ракетками. от обработки, если код уже обработал столкновение с исходным мячом? Удаление SKSpriteNode из родителя перед запуском взрыва не аннулирует другие контакты, они по-прежнему обрабатываются... так как я могу это сказать.. ЭЙ, ФИЗИЧЕСКИЕ КОНТАКТЫ... этого тела больше нет на картинке... так что просто выбросить эти контакты и не беспокоиться о них?

Я полагаю, я мог бы явно проверить, что у родителя все еще есть SKSpriteNode, доступный в коде контакта, прежде чем делать взрыв и т. Д., Но в лучшем случае это кажется неуклюжим, хотя я полагаю, что это сработает ... Есть ли другой/лучший способ справиться с этим? Я должен верить, что есть.


person Speckpgh    schedule 31.12.2013    source источник
comment
вы можете использовать для этого флаг, если хотите, и установить его, как только тело сталкивается в первый раз, и на основе этого установленного флага вы можете выполнить действие, а затем сбросить его, это всего лишь один из способов сделать это.   -  person spider1983    schedule 31.12.2013
comment
да, и сбросить флаг в didSimulatePhysics или в апдейте   -  person LearnCocos2D    schedule 31.12.2013
comment
Хотя это может сэкономить несколько циклов времени обработки, на самом деле это ничем не отличается от коллизии, просто проверяя, находится ли узел спрайта в родительском... Тем не менее, спасибо за предложение.   -  person Speckpgh    schedule 01.01.2014


Ответы (2)


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

Это должно предотвратить появление нескольких контактов для одного и того же узла.

Если вышеуказанное не работает, вы можете попробовать следующие методы:

  1. Удаление узла из родительского в делегате контакта и последующий запуск анимации взрыва.
  2. Подкласс SKSpriteNode или SKPhysicsBody для шаровых узлов и добавьте свойство, например. alreadyTouched. Затем вы можете проверить и установить свойство из контактного делегата.
person ZeMoon    schedule 31.12.2013
comment
Не сработало, установка для параметра contactTestBitMask значения 0 по-прежнему приводила к множественным столкновениям... - person Speckpgh; 01.01.2014
comment
опять же, это может сэкономить несколько циклов, но это все еще не что иное, как удаление из родителя, а затем при последующем вызове посмотреть, все еще ли он в родительском. Я надеялся на что-то, что напрямую сообщит физическому движку, что объект исчез, и отбросит все ожидающие действия, связанные с ним, но похоже, что оно не существует. Спасибо. - person Speckpgh; 27.01.2014
comment
Изменение contactTestbitMask не работает, потому что контакт уже произошел, SK уже создал объект SKPhysicsContact и вызовет для него didBeginContact. - person Steve Ives; 15.12.2016
comment
Только что увидел, сколько этому лет - извините! - person Steve Ives; 15.12.2016
comment
@SteveIves Спасибо за добавление нового ответа, чтобы сделать эту тему актуальной. - person ZeMoon; 15.12.2016

Если у вас есть три физических тела (ball, paddle1 и paddle2) и ball настроено на столкновение с ракетками (но ракетки не сталкиваются друг с другом) и мяч сталкивается с 2 ракетками во время одного и того же цикла обновления, то игровой движок сгенерирует 2 отдельные SKPhysicsContact объекты - ball и paddle1 и ball и paddle2.

didBegincontact (Swift2) или didBegin(contact:) (Swift 3) (dBC для краткости) будет вызываться дважды в течение одного и того же цикла update(), т. е. будет 2 вызова dBC между вызовами update()-, сначала для SKPhysicsContact между ball и paddle1, а затем для контакт между ball и paddle2. Вы можете сделать ball.removeFromParent() во время первого контакта, и шар будет удален из дерева узлов, но это не помешает второму вызову dBC для коллизии ball и paddle2, и вы, вероятно, выполните те же действия против ball (взрывание, удаление оценка и др.).

Самое простое, что можно сделать, это создать подкласс SKSPriteNode для вашего мяча (ballNode?) и добавить одно свойство isActive, инициализированное значением true. Это очень легко.

В dBC, когда мяч попадает в ракетку, проверьте его свойство isActive и, если false, просто return. Если это true, выполните обычные действия при столкновении, а затем установите для ball.isActive значение false. Когда dBC вызывается во второй раз, проверка на isActive предотвратит дублирование действий.

Вы также можете использовать userData мяча (часть SKSpriteNode) для хранения значений isActive, чтобы предотвратить создание подклассов, если хотите.

Есть и другие способы решить эту проблему, но пока я нашел этот способ самым простым.

person Steve Ives    schedule 15.12.2016