0
votes

I am trying to build some project using SCNPhysicsContactDelegate, but it I found that it detects contact between my nodes too early. I need it to be 100% precise and correct. I am attaching screenshot of too early contact detection. There is my code for theirs physics bodies:

nodeA code:

        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 code: (nodeB already exists, so I am only adding physics body)

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

contact function code:

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

bad collision image

Could you please someone help me find the solution? I look forward to your hearings guys.

Thanks Jakub

1
Perhaps turn on showPhysicsShapes in debugOptions so you can see what it's doing, and then play around with the different options for SCNPhysicsShape. Also, it's not 100% clear that it's actually rendering and displaying the frame where the contact is detected when you set isPaused. I'm not familiar enough with SceneKit's render loop to say. developer.apple.com/documentation/scenekit/scndebugoptionsbg2b
@bg2b As you can see in the screenshot, there are visible physicsShapes of the nodes, it is visible because I have enabled .showPhysicsShapes in debugOptions. And now I have had a look at the rendering loop of sceneKit and I found, that it is first simulating physics and after that it renders the scene.Jakub
@bg2b But the rendering loop is not the problem as I found now. developer.apple.com/documentation/scenekit/… There you can see, that it firstly simulate physics, then renders the scene and after rendering the scene it calls didRenderScene method. So i tried following:I created new variable var stopIt = false, then in physics world function, when the contact is triggered this code runs: stopIt = true, and then in didRenderScene method: if stopIt{ scene.isPaused = true}But after that result looks still the same.The box is still being stopped too earlyJakub
What are the velocities like? The scene has to go in discrete steps, so there will be one frame where there’s a gap and one frame later where the objects would overlap if not stopped by bouncing or whatnot. Is the picture showing possibly one frame early, i.e., before the bounce? Does it look obviously too early when in motion? If you slow the things down, does the contact indication happen at the same spot? If so, that suggests an imprecise collision, but if they get closer when moving slower, it suggests you’re getting the notification at the pre-touching frame.bg2b
What do you mean by "too early"? Unfortunately the attached image is very small and not self-explanatory.mnuages

1 Answers

0
votes

I found the solution! These two lines caused imprecise contact detection:

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

The problem was that, when you create SCNPhysicsShape() with node attribute it is imprecise, but when you create it with nodes geometry it all works totally right and precise. In my case the solution looks like this(replace the problem lines by these lines):

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