저는 SceneKit의 physicsBody 시스템을 사용하여 객체들 간의 충돌을 감지하고 매우 이상한 결과를 얻습니다. 설명하기 위해, 저는 운동학 물리학을 사용하여 두 개의 구체를 생성하는 최소한의 예제를 얻었습니다. 그리고 그것들을 간단히 겹쳐 지도록 직선으로 움직였습니다.SceneKit의 physicsWorld가 왜 단일 충돌에 대해 여러 번 발사 접촉합니까?
구체가 처음으로 겹칠 때 physicsWorld (: didBeginContact :)가 한 번만 호출되고 physicsWorld (: didEndContact :)가 중복 호출을 중지 할 때 한 번 호출됩니다. 대신 각 함수가 25 번 호출됩니다.
다음은 코드를 재현하는 코드입니다. Xcode 8.0에서는 "게임"템플릿을 사용하여 새로운 프로젝트를 만듭니다. 이와 함께 GameViewController.swift의 내용을 바꾸기 :
import UIKit
import SceneKit
class GameViewController: UIViewController, SCNSceneRendererDelegate, SCNPhysicsContactDelegate {
var scnScene: SCNScene!
var scnView: SCNView!
var cameraNode: SCNNode!
var nodeA: SCNNode!
var nodeB: SCNNode!
var countBeginnings: Int = 0
var countEndings: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
setupScene()
setupNodes()
}
func setupScene() {
// create a new SCNScene and feed it to the view
scnView = self.view as! SCNView
scnScene = SCNScene()
scnView.scene = scnScene
// assign self as SCNView delegate to get access to render loop
scnView.delegate = self
// assign self as contactDelegate to handle collisions
scnScene.physicsWorld.contactDelegate = self
// create the camera and position it at origin
cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3Zero
scnScene.rootNode.addChildNode(cameraNode)
// tell scnView to update every frame
scnView.isPlaying = true
}
func setupNodes() {
// create two spheres with physicsBodies, one inside the other
nodeA = SCNNode()
nodeA.name = "Node A"
nodeA.geometry = SCNSphere(radius: 1.0)
nodeA.geometry!.firstMaterial?.diffuse.contents = UIColor.yellow.withAlphaComponent(0.6)
// expected behavior
// nodeA.position = SCNVector3(x: 0.0, y: -0.8, z: -10.0)
// weird behavior
nodeA.position = SCNVector3(x: 0.0, y: -0.9, z: -10.0)
nodeA.physicsBody = SCNPhysicsBody(type: .kinematic, shape: SCNPhysicsShape(geometry: nodeA.geometry!, options: nil))
scnScene.rootNode.addChildNode(nodeA)
nodeB = SCNNode()
nodeB.name = "Node B"
nodeB.geometry = SCNSphere(radius: 0.5)
nodeB.geometry!.firstMaterial?.diffuse.contents = UIColor.red
nodeB.position = SCNVector3(x: -2.0, y: 0.0, z: -10.0)
nodeB.physicsBody = SCNPhysicsBody(type: .kinematic, shape: SCNPhysicsShape(geometry: nodeB.geometry!, options: nil))
scnScene.rootNode.addChildNode(nodeB)
// node A can collide with node B but not the other way around
nodeA.physicsBody!.categoryBitMask = 2
nodeB.physicsBody!.categoryBitMask = 1
nodeA.physicsBody!.contactTestBitMask = 1
}
func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
countBeginnings += 1
print("(" + String(countBeginnings) + ") " + contact.nodeA.name! + " began contact with " + contact.nodeB.name!)
}
func physicsWorld(_ world: SCNPhysicsWorld, didEnd contact: SCNPhysicsContact) {
countEndings += 1
print("(" + String(countEndings) + ") " + contact.nodeA.name! + " ended contact with " + contact.nodeB.name!)
}
var frameNumber = 0
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
nodeB.position.x += 0.01
nodeB.position.y -= 0.01
}
}
도 계속 다른 불확실성이있다. 나는 구체의 하나의 초기 위치를 변경하면 조금,은 y -0.9에서 -0.8로 위치 이동 : 이제
nodeA.position = SCNVector3(x: 0.0, y: -0.8, z: -10.0)
내가 예상되는 동작, 하나의 호출이 시작에 도착하고 하나의 호출은 종료합니다 ! 약간 다른 충돌 각은 완전히 다른 동작을 초래합니다.
이것은 SceneKit 버그일까요? 아니면 실제로 예상되는 동작입니까?
내가 실수라고 생각합니다. 왜 그랬을까요? 시작하고 충돌 했나요? 둘 다 충돌의 모든 프레임에 대해 부름 받았습니까? 그들 사이의 차이점은 무엇입니까? – Robert
예를 들어 보셨습니까? didBegin과 didEnd는 충돌이있는 모든 프레임에서 호출되지 않으며 항상 같은 프레임에서 호출되는 것은 아닙니다. 또한 앞서 언급 한 초기 조건을 변경하면 겹치는 첫 번째 프레임에서 didBegin을 한 번만 호출하고 처음 프레임에서는 didEnd를 한 번만 호출하면 많은 프레임에서 해당 영역이 교차하는 것을 볼 수 있습니다. – Robert
수정 된 답변 확인 –