SceneKit의 SCNPhysicsContactDelegate에서 충돌 결정

11808 단어 SceneKitiOSSwiftARKit
대호평의 「페차바트」에도 이용되고 있는 SceneKit의 물리 판정 API, Physics에 대해서를 쓰고 싶습니다.



SCNPhysicsContactDelegate



자주 사용된다고 생각하는 것이, SCNPhysicsContactDelegate 그리고, 당 판정이 발생했을 때에 불리는 메소드가 이하와 같이 정의되고 있습니다.
  • func physicsWorld (SCNPhysicsWorld, didBegin : SCNPhysicsContact)
  • func physicsWorld(SCNPhysicsWorld, didUpdate: SCNPhysicsContact)
  • func physicsWorld(SCNPhysicsWorld, didEnd: SCNPhysicsContact)

  • didBegin, didUpdate, didEnd로 불리는 3 종류의 메소드가 있어, 각각 불리는 타이밍이 다릅니다. 이번은 물체끼리의 충돌이 끝나면 불리는, didBegin을 예로, 실제로 2개의 물체가 부딪쳤을 때의 핸들링 방법을 간단하게 소개합니다.

    우선은 Delegate를 세트



    먼저 sceneView.scene.physicsWorld의 contactDelegate에 ViewController를 설정합니다.
    override func viewDidLoad() {
        super.viewDidLoad()
    
        sceneView.scene.physicsWorld.contactDelegate = self
    }
    
    extension ViewController: SCNPhysicsContactDelegate {
        func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
    
        }
    }
    

    맞으면 호출되는 메서드 정의



    그리고 SCNPhysicsContactDelegate의 physicsWorld (didBegin을 정의합니다.

    인수에는 SCNPhysicsWorld와 SCNPhysicsContact가 있으며, 전자는 환경의 정보, 후자는 당 판정의 정보입니다.
    func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
        let nodeA = contact.nodeA
        let nodeB = contact.nodeB
    }
    

    다음과 같은 경우에는 contact.nodeA 또는 contact.nodeB에 파란색 공 또는 빨간 마토의 Node가 각각 설정되어 있습니다.



    당 판정을 실시한다



    예를 들면, 다음과 같이 적의 Node와 볼의 Node가 정의되어 있다고 합시다.
    let matoNode = SCNNode()
    matoNode.name = "mato"
    
    let ballNode = SCNNode()
    ballNode.name = "ball"
    

    그 경우 SCNPhysicsContactDelegate의 메소드에 있어서, 이하와 같이 맞았는지 어떤지를 판정합니다. (더 똑똑한 쓰기 방법이있을 수 있습니다)
    func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
        let nodeA = contact.nodeA
        let nodeB = contact.nodeB
    
        if (nodeA.name == "mato" && nodeB.name == "ball") || (nodeB.name == "mato" && nodeA.name == "ball") {
            // 当たった!!
        }
    }
    

    치면 햅틱 피드백을 하거나 상대방에게 정보를 전송하여 슈팅 배틀을 수립할 수 있습니다.

    당 판정을 실시하기 위한 Node의 설정



    실은, 단지 단순히 Node를 설정한 것만으로는, 당 판정은 발화하지 않습니다. 먼저 올린 마토의 Node와 볼의 Node를 각각 구체적으로 설정해 봅시다.

    마토의 노드



    SCNPhysicsShape를 설정해야 합니다. geometry를 인수에 걸립니다.
    let cylinder = SCNCylinder(radius: 0.1, height: 0.05)
    let matoNode = SCNNode(geometry: box)
    node.name = "mato"
    node.position = SCNVector3Make(0, 0, -1.5)
    
    // add PhysicsShape
    let shape = SCNPhysicsShape(geometry: cylinder, options: nil)
    node.physicsBody = SCNPhysicsBody(type: .dynamic, shape: shape)
    node.physicsBody?.isAffectedByGravity = false
    

    공의 Node



    맞는 쪽의 SCNPhysicsBody에 contactTestBitMask를 설정하는 것을 잊지 마세요!
    이쪽 디폴트는 0입니다만, 그대로라면 당 판정이 발화하지 않습니다.
    let ball = SCNSphere(radius: 0.1)
    ball.firstMaterial?.diffuse.contents = UIColor.blue
    
    let ballNode = SCNNode(geometry: ball)
    ballNode.name = "ball"
    
    // add PhysicsShape
    let shape = SCNPhysicsShape(geometry: ball, options: nil)
    ballNode.physicsBody = SCNPhysicsBody(type: .dynamic, shape: shape)
    ballNode.physicsBody?.contactTestBitMask = 1
    ballNode.physicsBody?.isAffectedByGravity = false
    

    이상!

    요약


  • SceneKit의 SCNPhysicsContactDelegate 메서드에는 세 가지 유형이 있습니다.
  • SCNPhysicsContact에서 노드 A와 노드 B가 있으므로 이름에서 어떤 노드와 어떤 노드가 충돌했는지 결정할 수 있습니다.
  • SCNPhysicsShape를 설정하는 것을 잊지 마세요
  • 맞는 쪽에는 ContactTestBitMask도 잊지 말고

  • 샘플 코드



    htps : // 기주 b. 코 m / k 보 y-시 lゔぇrgym / 아 의 Physics에 있습니다!

    유용한 기사


  • SpriteKit의 CategoryBitMask, CollisionBitMask, ContactTestBitMask 요약
  • iOS에서 SceneKit 사용하기 (Swift 3) Part 66
  • 좋은 웹페이지 즐겨찾기