Swift SceneKit: почему он слишком рано обнаруживает контакт между узлами?

Я пытаюсь создать какой-то проект с использованием SCNPhysicsContactDelegate, но обнаружил, что он слишком рано обнаруживает контакт между моими узлами. Мне нужно, чтобы это было на 100% точным и правильным. Прилагаю скриншот слишком раннего обнаружения контакта. Вот мой код для их физических тел:

код узлаA:

        nodeA = SCNNode(geometry: SCNBox(width: 0.3, height: 0.3, length: 0.3, chamferRadius: 0.05))
        nodeA.position = SCNVector3(0, 3.3, 0)
        nodeA.geometry?.firstMaterial?.diffuse.contents = UIColor.red
        nodeA.physicsBody = SCNPhysicsBody.dynamic()
        nodeA.physicsBody?.physicsShape = SCNPhysicsShape(node: nodeA, options: nil)
        nodeA.physicsBody?.categoryBitMask = PhysicsCategories.nodeA
        nodeA.physicsBody?.contactTestBitMask = PhysicsCategories.nodeB
        nodeA.physicsBody?.isAffectedByGravity = false
        nodeA.name = "nodeA"
        nodeA.opacity = 0
        self.scene.rootNode.addChildNode(self.nodeA)

код nodeB: (nodeB уже существует, поэтому я добавляю только физическое тело)

        nodeB.physicsBody = SCNPhysicsBody.kinematic()
        nodeB.physicsBody?.physicsShape = SCNPhysicsShape(node: nodeB, options: nil)
        nodeB.physicsBody?.categoryBitMask = PhysicsCategories.nodeB
        nodeB.physicsBody?.contactTestBitMask = PhysicsCategories.nodeA

Код функции контакта:

        func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
            scene.isPaused = true
        }

плохое изображение столкновения

Не могли бы вы помочь мне найти решение? Я с нетерпением жду ваших слушаний, ребята.

Спасибо, Якуб.


person Jakub    schedule 25.11.2019    source источник
comment
Возможно, включите showPhysicsShapes в debugOptions, чтобы вы могли видеть, что он делает, а затем поэкспериментируйте с различными параметрами SCNPhysicsShape. Кроме того, не на 100% ясно, что на самом деле рендеринг и отображение кадра, в котором обнаружен контакт, когда вы устанавливаете isPaused. Я недостаточно знаком с циклом рендеринга SceneKit, чтобы сказать. developer.apple.com/documentation/scenekit/scndebugoptions   -  person bg2b    schedule 26.11.2019
comment
@bg2b Как вы можете видеть на скриншоте, видны физико-физические формы узлов, они видны, потому что я включил .showPhysicsShapes в debugOptions. И теперь я взглянул на цикл рендеринга sceneKit и обнаружил, что он сначала имитирует физику, а затем рендерит сцену.   -  person Jakub    schedule 26.11.2019
comment
@ bg2b Но проблема не в цикле рендеринга, как я обнаружил сейчас. developer.apple.com/documentation/scenekit/ Там видно, что сначала имитирует физику, затем визуализирует сцену и после рендеринга сцены вызывает метод didRenderScene. Итак, я попробовал следующее: я создал новую переменную var stopIt = false, затем в функции мира физики, когда запускается контакт, запускается этот код: stopIt = true, а затем в методе didRenderScene: if stopIt{ scene.isPaused = true}Но после этого результат выглядит все так же. остановился слишком рано   -  person Jakub    schedule 26.11.2019
comment
Каковы скорости? Сцена должна идти дискретными шагами, поэтому будет один кадр, где есть разрыв, и один кадр позже, где объекты будут перекрываться, если их не остановить отскоком или чем-то еще. Возможно, изображение показывает на один кадр раньше, т. е. до отскока? В движении это выглядит явно слишком рано? Если вы замедляете работу, происходит ли индикация контакта в том же месте? Если это так, это предполагает неточное столкновение, но если они приближаются при более медленном движении, это предполагает, что вы получаете уведомление в кадре до касания.   -  person bg2b    schedule 26.11.2019
comment
Что вы имеете в виду под слишком рано? К сожалению, приложенное изображение очень маленькое и не говорит само за себя.   -  person mnuages    schedule 26.11.2019
comment
@mnuages ​​Под слишком ранним я подразумеваю, что он обнаруживает столкновение до того, как станет видимым касание.   -  person Jakub    schedule 26.11.2019


Ответы (1)


Я нашел решение! Эти две строки вызвали неточное определение контакта:

nodeA.physicsBody?.physicsShape = SCNPhysicsShape(node: nodeA, options: nil) и nodeB.physicsBody?.physicsShape = SCNPhysicsShape(node: nodeB, options: nil).

Проблема заключалась в том, что когда вы создаете SCNPhysicsShape() с атрибутом узла, он неточен, но когда вы создаете его с геометрией узлов, все работает совершенно правильно и точно. В моем случае решение выглядит так (замените проблемные строки на эти строки):

nodeA.physicsBody?.physicsShape = SCNPhysicsShape(geometry: SCNBox(width: 0.3, height: 0.3, length: 0.3, chamferRadius: 0.05), options: nil) и nodeB.physicsBody?.physicsShape = SCNPhysicsShape(geometry: SCNBox(width: 0.1, height: 0.5, length: 1, chamferRadius: 0), options: nil)

person Jakub    schedule 27.11.2019