Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

Strange use of "whether ... than ..." in official text

Could a dragon use its wings to swim?

Car headlights in a world without electricity

How to avoid supervisors with prejudiced views?

Is the offspring between a demon and a celestial possible? If so what is it called and is it in a book somewhere?

Can I board the first leg of the flight without having final country's PR card?

subequations: How to continue numbering within subequation?

How do you define an element with an ID attribute using LWC?

Relevant Part for a Badminton Serve

What CSS properties can the br tag have?

What are the unusually-enlarged wing sections on this P-38 Lightning?

Why did early computer designers eschew integers?

Is it a bad idea to plug the other end of ESD strap to wall ground?

Magento 1.9 observer on only new product added ( no updated product )

Airplane gently rocking its wings during whole flight

It is correct to match light sources with the same color temperature?

Cardinal characteristics of amorphous sets

DISTINCT column combination with permutations

Single word request for not liking to be touched

Ising model simulation

Players Circumventing the limitations of Wish

Why was Sir Cadogan fired?

From jafe to El-Guest

Can I send my tax returns from abroad to IRS Austin



Swift 4 - func physicsWorld not invoked on collision?



The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags










-1















I'm trying to make a collision effect when my jet is hit by a bullet or touched by the player directly. The animation and the touch explosion works.



But when the bullet hits the jet planes it's not exploding.



Note: Already tried adding
sceneView.scene.physicsWorld.contactDelegate = self in viewDidLoad()



//
// ViewController.swift
//

import UIKit
import SceneKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate, SCNPhysicsContactDelegate
// MARK: - Variables
@IBOutlet var sceneView: ARSCNView!
var visNode: SCNNode!
var mainContainer: SCNNode!
var gameHasStarted = false
var foundSurface = false
var gamePos = SCNVector3Make(0.0, 0.0, 0.0)
var scoreLbl: UILabel!


var player: AVAudioPlayer!


var score = 0
didSet
scoreLbl.text = "(score)"



// MARK: - View Controller Handling
override func viewDidLoad()
super.viewDidLoad()

// Scene
sceneView.delegate = self
sceneView.showsStatistics = true

let scene = SCNScene(named: "art.scnassets/scene.scn")!
sceneView.scene = scene

sceneView.scene.physicsWorld.contactDelegate = self


override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)

//let configuration = ARWorldTrackingConfiguration()
//sceneView.session.run(configuration)


self.configureSession()


override func viewWillDisappear(_ animated: Bool)
super.viewWillDisappear(animated)

sceneView.session.pause()


// MARK: - Custom functions
func randomPos() -> SCNVector3
let randX = (Float(arc4random_uniform(200)) / 100.0) - 1.0
let randY = (Float(arc4random_uniform(100)) / 100.0) + 1.5

return SCNVector3Make(randX, randY, -5.0)


@objc func addPlane()
let plane = sceneView.scene.rootNode.childNode(withName: "plane", recursively: false)?.copy() as! SCNNode
plane.position = randomPos()
plane.isHidden = false

mainContainer.addChildNode(plane)

let randSpeed = Float(arc4random_uniform(3) + 1)
//original - let randSpeed = Float(arc4random_uniform(3) + 3)
let planeAnimation = SCNAction.sequence([SCNAction.wait(duration: 10.0), SCNAction.fadeOut(duration: 1.0), SCNAction.removeFromParentNode()])
plane.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
plane.physicsBody?.isAffectedByGravity = false

plane.physicsBody?.categoryBitMask = CollisionCategory.ship.rawValue
plane.physicsBody?.contactTestBitMask = CollisionCategory.bullets.rawValue


plane.physicsBody?.applyForce(SCNVector3Make(0.0, 0.0, randSpeed), asImpulse: true)
plane.runAction(planeAnimation)

Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(addPlane), userInfo: nil, repeats: false)


func getUserVector() -> (SCNVector3, SCNVector3) // (direction, position)
if let frame = self.sceneView.session.currentFrame
let mat = SCNMatrix4(frame.camera.transform) // 4x4 transform matrix describing camera in world space
let dir = SCNVector3(-30 * mat.m31, -30 * mat.m32, -10 * mat.m33) // orientation of camera in world space
let pos = SCNVector3(mat.m41, mat.m42, mat.m43) // location of camera in world space

return (dir, pos)

return (SCNVector3(0, 0, -1), SCNVector3(0, 0, -0.2))


// MARK: - Scene Handling
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
if gameHasStarted


let bulletsNode = Bullet()

let (direction, position) = self.getUserVector()
bulletsNode.position = position // SceneKit/AR coordinates are in meters

let bulletDirection = direction

bulletsNode.physicsBody?.velocity = SCNVector3Make(0.0, 0.0, -5)
bulletsNode.physicsBody?.applyForce(bulletDirection, asImpulse: true)
sceneView.scene.rootNode.addChildNode(bulletsNode)


guard let touch = touches.first else return
let touchLocation = touch.location(in: view)

guard let hitTestTouch = sceneView.hitTest(touchLocation, options: nil).first else return
let touchedNode = hitTestTouch.node

guard touchedNode.name == "plane" else return
touchedNode.physicsBody?.isAffectedByGravity = true
touchedNode.physicsBody?.applyTorque(SCNVector4Make(0.0, 0.3, 1.0, 1.0), asImpulse: true)
score += 1

let explosion = SCNParticleSystem(named: "Explosion.scnp", inDirectory: nil)!
touchedNode.addParticleSystem(explosion)
else
guard foundSurface else return

gameHasStarted = true
visNode.removeFromParentNode()

// Score Lbl
scoreLbl = UILabel(frame: CGRect(x: 0.0, y: view.frame.height * 0.05, width: view.frame.width, height: view.frame.height * 0.1))
scoreLbl.textColor = .yellow
scoreLbl.font = UIFont(name: "Arial", size: view.frame.width * 0.1)
scoreLbl.text = "0"
scoreLbl.textAlignment = .center

view.addSubview(scoreLbl)

// Main Container
mainContainer = sceneView.scene.rootNode.childNode(withName: "mainContainer", recursively: false)!
mainContainer.isHidden = false
mainContainer.position = gamePos

// Lighting (Ambient)
let ambientLight = SCNLight()
ambientLight.type = .ambient
ambientLight.color = UIColor.white
ambientLight.intensity = 300.0

let ambientLightNode = SCNNode()
ambientLightNode.light = ambientLight
ambientLightNode.position.y = 2.0

mainContainer.addChildNode(ambientLightNode)

// Lighting (Omnidirectional)
let omniLight = SCNLight()
omniLight.type = .omni
omniLight.color = UIColor.white
omniLight.intensity = 1000.0

let omniLightNode = SCNNode()
omniLightNode.light = omniLight
omniLightNode.position.y = 3.0

mainContainer.addChildNode(omniLightNode)

addPlane()



func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval)
guard !gameHasStarted else return
guard let hitTest = sceneView.hitTest(CGPoint(x: view.frame.midX, y: view.frame.midY), types: [.existingPlane, .featurePoint, .estimatedHorizontalPlane]).last else return

let transform = SCNMatrix4(hitTest.worldTransform)
gamePos = SCNVector3Make(transform.m41, transform.m42, transform.m43)

if visNode == nil
let visPlane = SCNPlane(width: 0.3, height: 0.3)
visPlane.firstMaterial?.diffuse.contents = #imageLiteral(resourceName: "tracker")

visNode = SCNNode(geometry: visPlane)
visNode.eulerAngles.x = .pi * -0.5

sceneView.scene.rootNode.addChildNode(visNode)


visNode.position = gamePos
foundSurface = true


func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact)


func removeNodeWithAnimation(_ node: SCNNode, explosion: Bool)

// Play collision sound for all collisions (bullet-bullet, etc.)

self.playSoundEffect(ofType: .collision)

if explosion

// Play explosion sound for bullet-ship collisions

self.playSoundEffect(ofType: .explosion)

let particleSystem = SCNParticleSystem(named: "Explosion", inDirectory: nil)
let systemNode = SCNNode()
systemNode.addParticleSystem(particleSystem!)
// place explosion where node is
systemNode.position = node.position
sceneView.scene.rootNode.addChildNode(systemNode)


// remove node
node.removeFromParentNode()


// MARK: - Sound Effects

func playSoundEffect(ofType effect: SoundEffect)

// Async to avoid substantial cost to graphics processing (may result in sound effect delay however)
DispatchQueue.main.async
do

if let effectURL = Bundle.main.url(forResource: effect.rawValue, withExtension: "mp3")

self.player = try AVAudioPlayer(contentsOf: effectURL)
self.player.play()



catch let error as NSError
print(error.description)




func configureSession()
if ARWorldTrackingConfiguration.isSupported // checks if user's device supports the more precise ARWorldTrackingSessionConfiguration
// equivalent to `if utsname().hasAtLeastA9()`
// Create a session configuration
let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = ARWorldTrackingConfiguration.PlaneDetection.horizontal

// Run the view's session
sceneView.session.run(configuration)
else
// slightly less immersive AR experience due to lower end processor
let configuration = AROrientationTrackingConfiguration()

// Run the view's session
sceneView.session.run(configuration)






struct CollisionCategory: OptionSet
let rawValue: Int

static let bullets = CollisionCategory(rawValue: 1 << 0) // 00...01
static let ship = CollisionCategory(rawValue: 1 << 1) // 00..10


extension utsname
func hasAtLeastA9() -> Bool // checks if device has at least A9 chip for configuration
var systemInfo = self
uname(&systemInfo)
let str = withUnsafePointer(to: &systemInfo.machine.0) ptr in
return String(cString: ptr)

switch str
case "iPhone8,1", "iPhone8,2", "iPhone8,4", "iPhone9,1", "iPhone9,2", "iPhone9,3", "iPhone9,4": // iphone with at least A9 processor
return true
case "iPad6,7", "iPad6,8", "iPad6,3", "iPad6,4", "iPad6,11", "iPad6,12": // ipad with at least A9 processor
return true
default:
return false




enum SoundEffect: String
case explosion = "explosion"
case collision = "collision"
case torpedo = "torpedo"



Bullet.swift



import UIKit
import SceneKit

// Spheres that are shot at the "ships"
class Bullet: SCNNode
override init ()
super.init()
let sphere = SCNSphere(radius: 0.025)
self.geometry = sphere
let shape = SCNPhysicsShape(geometry: sphere, options: nil)
self.physicsBody = SCNPhysicsBody(type: .dynamic, shape: shape)
self.physicsBody?.isAffectedByGravity = false
// see http://texnotes.me/post/5/ for details on collisions and bit masks
self.physicsBody?.categoryBitMask = CollisionCategory.bullets.rawValue
self.physicsBody?.contactTestBitMask = CollisionCategory.ship.rawValue

// add texture
let material = SCNMaterial()
material.diffuse.contents = UIImage(named: "bullet_texture")
self.geometry?.materials = [material]


required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")











share|improve this question


























    -1















    I'm trying to make a collision effect when my jet is hit by a bullet or touched by the player directly. The animation and the touch explosion works.



    But when the bullet hits the jet planes it's not exploding.



    Note: Already tried adding
    sceneView.scene.physicsWorld.contactDelegate = self in viewDidLoad()



    //
    // ViewController.swift
    //

    import UIKit
    import SceneKit
    import ARKit

    class ViewController: UIViewController, ARSCNViewDelegate, SCNPhysicsContactDelegate
    // MARK: - Variables
    @IBOutlet var sceneView: ARSCNView!
    var visNode: SCNNode!
    var mainContainer: SCNNode!
    var gameHasStarted = false
    var foundSurface = false
    var gamePos = SCNVector3Make(0.0, 0.0, 0.0)
    var scoreLbl: UILabel!


    var player: AVAudioPlayer!


    var score = 0
    didSet
    scoreLbl.text = "(score)"



    // MARK: - View Controller Handling
    override func viewDidLoad()
    super.viewDidLoad()

    // Scene
    sceneView.delegate = self
    sceneView.showsStatistics = true

    let scene = SCNScene(named: "art.scnassets/scene.scn")!
    sceneView.scene = scene

    sceneView.scene.physicsWorld.contactDelegate = self


    override func viewWillAppear(_ animated: Bool)
    super.viewWillAppear(animated)

    //let configuration = ARWorldTrackingConfiguration()
    //sceneView.session.run(configuration)


    self.configureSession()


    override func viewWillDisappear(_ animated: Bool)
    super.viewWillDisappear(animated)

    sceneView.session.pause()


    // MARK: - Custom functions
    func randomPos() -> SCNVector3
    let randX = (Float(arc4random_uniform(200)) / 100.0) - 1.0
    let randY = (Float(arc4random_uniform(100)) / 100.0) + 1.5

    return SCNVector3Make(randX, randY, -5.0)


    @objc func addPlane()
    let plane = sceneView.scene.rootNode.childNode(withName: "plane", recursively: false)?.copy() as! SCNNode
    plane.position = randomPos()
    plane.isHidden = false

    mainContainer.addChildNode(plane)

    let randSpeed = Float(arc4random_uniform(3) + 1)
    //original - let randSpeed = Float(arc4random_uniform(3) + 3)
    let planeAnimation = SCNAction.sequence([SCNAction.wait(duration: 10.0), SCNAction.fadeOut(duration: 1.0), SCNAction.removeFromParentNode()])
    plane.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
    plane.physicsBody?.isAffectedByGravity = false

    plane.physicsBody?.categoryBitMask = CollisionCategory.ship.rawValue
    plane.physicsBody?.contactTestBitMask = CollisionCategory.bullets.rawValue


    plane.physicsBody?.applyForce(SCNVector3Make(0.0, 0.0, randSpeed), asImpulse: true)
    plane.runAction(planeAnimation)

    Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(addPlane), userInfo: nil, repeats: false)


    func getUserVector() -> (SCNVector3, SCNVector3) // (direction, position)
    if let frame = self.sceneView.session.currentFrame
    let mat = SCNMatrix4(frame.camera.transform) // 4x4 transform matrix describing camera in world space
    let dir = SCNVector3(-30 * mat.m31, -30 * mat.m32, -10 * mat.m33) // orientation of camera in world space
    let pos = SCNVector3(mat.m41, mat.m42, mat.m43) // location of camera in world space

    return (dir, pos)

    return (SCNVector3(0, 0, -1), SCNVector3(0, 0, -0.2))


    // MARK: - Scene Handling
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
    if gameHasStarted


    let bulletsNode = Bullet()

    let (direction, position) = self.getUserVector()
    bulletsNode.position = position // SceneKit/AR coordinates are in meters

    let bulletDirection = direction

    bulletsNode.physicsBody?.velocity = SCNVector3Make(0.0, 0.0, -5)
    bulletsNode.physicsBody?.applyForce(bulletDirection, asImpulse: true)
    sceneView.scene.rootNode.addChildNode(bulletsNode)


    guard let touch = touches.first else return
    let touchLocation = touch.location(in: view)

    guard let hitTestTouch = sceneView.hitTest(touchLocation, options: nil).first else return
    let touchedNode = hitTestTouch.node

    guard touchedNode.name == "plane" else return
    touchedNode.physicsBody?.isAffectedByGravity = true
    touchedNode.physicsBody?.applyTorque(SCNVector4Make(0.0, 0.3, 1.0, 1.0), asImpulse: true)
    score += 1

    let explosion = SCNParticleSystem(named: "Explosion.scnp", inDirectory: nil)!
    touchedNode.addParticleSystem(explosion)
    else
    guard foundSurface else return

    gameHasStarted = true
    visNode.removeFromParentNode()

    // Score Lbl
    scoreLbl = UILabel(frame: CGRect(x: 0.0, y: view.frame.height * 0.05, width: view.frame.width, height: view.frame.height * 0.1))
    scoreLbl.textColor = .yellow
    scoreLbl.font = UIFont(name: "Arial", size: view.frame.width * 0.1)
    scoreLbl.text = "0"
    scoreLbl.textAlignment = .center

    view.addSubview(scoreLbl)

    // Main Container
    mainContainer = sceneView.scene.rootNode.childNode(withName: "mainContainer", recursively: false)!
    mainContainer.isHidden = false
    mainContainer.position = gamePos

    // Lighting (Ambient)
    let ambientLight = SCNLight()
    ambientLight.type = .ambient
    ambientLight.color = UIColor.white
    ambientLight.intensity = 300.0

    let ambientLightNode = SCNNode()
    ambientLightNode.light = ambientLight
    ambientLightNode.position.y = 2.0

    mainContainer.addChildNode(ambientLightNode)

    // Lighting (Omnidirectional)
    let omniLight = SCNLight()
    omniLight.type = .omni
    omniLight.color = UIColor.white
    omniLight.intensity = 1000.0

    let omniLightNode = SCNNode()
    omniLightNode.light = omniLight
    omniLightNode.position.y = 3.0

    mainContainer.addChildNode(omniLightNode)

    addPlane()



    func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval)
    guard !gameHasStarted else return
    guard let hitTest = sceneView.hitTest(CGPoint(x: view.frame.midX, y: view.frame.midY), types: [.existingPlane, .featurePoint, .estimatedHorizontalPlane]).last else return

    let transform = SCNMatrix4(hitTest.worldTransform)
    gamePos = SCNVector3Make(transform.m41, transform.m42, transform.m43)

    if visNode == nil
    let visPlane = SCNPlane(width: 0.3, height: 0.3)
    visPlane.firstMaterial?.diffuse.contents = #imageLiteral(resourceName: "tracker")

    visNode = SCNNode(geometry: visPlane)
    visNode.eulerAngles.x = .pi * -0.5

    sceneView.scene.rootNode.addChildNode(visNode)


    visNode.position = gamePos
    foundSurface = true


    func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact)


    func removeNodeWithAnimation(_ node: SCNNode, explosion: Bool)

    // Play collision sound for all collisions (bullet-bullet, etc.)

    self.playSoundEffect(ofType: .collision)

    if explosion

    // Play explosion sound for bullet-ship collisions

    self.playSoundEffect(ofType: .explosion)

    let particleSystem = SCNParticleSystem(named: "Explosion", inDirectory: nil)
    let systemNode = SCNNode()
    systemNode.addParticleSystem(particleSystem!)
    // place explosion where node is
    systemNode.position = node.position
    sceneView.scene.rootNode.addChildNode(systemNode)


    // remove node
    node.removeFromParentNode()


    // MARK: - Sound Effects

    func playSoundEffect(ofType effect: SoundEffect)

    // Async to avoid substantial cost to graphics processing (may result in sound effect delay however)
    DispatchQueue.main.async
    do

    if let effectURL = Bundle.main.url(forResource: effect.rawValue, withExtension: "mp3")

    self.player = try AVAudioPlayer(contentsOf: effectURL)
    self.player.play()



    catch let error as NSError
    print(error.description)




    func configureSession()
    if ARWorldTrackingConfiguration.isSupported // checks if user's device supports the more precise ARWorldTrackingSessionConfiguration
    // equivalent to `if utsname().hasAtLeastA9()`
    // Create a session configuration
    let configuration = ARWorldTrackingConfiguration()
    configuration.planeDetection = ARWorldTrackingConfiguration.PlaneDetection.horizontal

    // Run the view's session
    sceneView.session.run(configuration)
    else
    // slightly less immersive AR experience due to lower end processor
    let configuration = AROrientationTrackingConfiguration()

    // Run the view's session
    sceneView.session.run(configuration)






    struct CollisionCategory: OptionSet
    let rawValue: Int

    static let bullets = CollisionCategory(rawValue: 1 << 0) // 00...01
    static let ship = CollisionCategory(rawValue: 1 << 1) // 00..10


    extension utsname
    func hasAtLeastA9() -> Bool // checks if device has at least A9 chip for configuration
    var systemInfo = self
    uname(&systemInfo)
    let str = withUnsafePointer(to: &systemInfo.machine.0) ptr in
    return String(cString: ptr)

    switch str
    case "iPhone8,1", "iPhone8,2", "iPhone8,4", "iPhone9,1", "iPhone9,2", "iPhone9,3", "iPhone9,4": // iphone with at least A9 processor
    return true
    case "iPad6,7", "iPad6,8", "iPad6,3", "iPad6,4", "iPad6,11", "iPad6,12": // ipad with at least A9 processor
    return true
    default:
    return false




    enum SoundEffect: String
    case explosion = "explosion"
    case collision = "collision"
    case torpedo = "torpedo"



    Bullet.swift



    import UIKit
    import SceneKit

    // Spheres that are shot at the "ships"
    class Bullet: SCNNode
    override init ()
    super.init()
    let sphere = SCNSphere(radius: 0.025)
    self.geometry = sphere
    let shape = SCNPhysicsShape(geometry: sphere, options: nil)
    self.physicsBody = SCNPhysicsBody(type: .dynamic, shape: shape)
    self.physicsBody?.isAffectedByGravity = false
    // see http://texnotes.me/post/5/ for details on collisions and bit masks
    self.physicsBody?.categoryBitMask = CollisionCategory.bullets.rawValue
    self.physicsBody?.contactTestBitMask = CollisionCategory.ship.rawValue

    // add texture
    let material = SCNMaterial()
    material.diffuse.contents = UIImage(named: "bullet_texture")
    self.geometry?.materials = [material]


    required init?(coder aDecoder: NSCoder)
    fatalError("init(coder:) has not been implemented")











    share|improve this question
























      -1












      -1








      -1








      I'm trying to make a collision effect when my jet is hit by a bullet or touched by the player directly. The animation and the touch explosion works.



      But when the bullet hits the jet planes it's not exploding.



      Note: Already tried adding
      sceneView.scene.physicsWorld.contactDelegate = self in viewDidLoad()



      //
      // ViewController.swift
      //

      import UIKit
      import SceneKit
      import ARKit

      class ViewController: UIViewController, ARSCNViewDelegate, SCNPhysicsContactDelegate
      // MARK: - Variables
      @IBOutlet var sceneView: ARSCNView!
      var visNode: SCNNode!
      var mainContainer: SCNNode!
      var gameHasStarted = false
      var foundSurface = false
      var gamePos = SCNVector3Make(0.0, 0.0, 0.0)
      var scoreLbl: UILabel!


      var player: AVAudioPlayer!


      var score = 0
      didSet
      scoreLbl.text = "(score)"



      // MARK: - View Controller Handling
      override func viewDidLoad()
      super.viewDidLoad()

      // Scene
      sceneView.delegate = self
      sceneView.showsStatistics = true

      let scene = SCNScene(named: "art.scnassets/scene.scn")!
      sceneView.scene = scene

      sceneView.scene.physicsWorld.contactDelegate = self


      override func viewWillAppear(_ animated: Bool)
      super.viewWillAppear(animated)

      //let configuration = ARWorldTrackingConfiguration()
      //sceneView.session.run(configuration)


      self.configureSession()


      override func viewWillDisappear(_ animated: Bool)
      super.viewWillDisappear(animated)

      sceneView.session.pause()


      // MARK: - Custom functions
      func randomPos() -> SCNVector3
      let randX = (Float(arc4random_uniform(200)) / 100.0) - 1.0
      let randY = (Float(arc4random_uniform(100)) / 100.0) + 1.5

      return SCNVector3Make(randX, randY, -5.0)


      @objc func addPlane()
      let plane = sceneView.scene.rootNode.childNode(withName: "plane", recursively: false)?.copy() as! SCNNode
      plane.position = randomPos()
      plane.isHidden = false

      mainContainer.addChildNode(plane)

      let randSpeed = Float(arc4random_uniform(3) + 1)
      //original - let randSpeed = Float(arc4random_uniform(3) + 3)
      let planeAnimation = SCNAction.sequence([SCNAction.wait(duration: 10.0), SCNAction.fadeOut(duration: 1.0), SCNAction.removeFromParentNode()])
      plane.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
      plane.physicsBody?.isAffectedByGravity = false

      plane.physicsBody?.categoryBitMask = CollisionCategory.ship.rawValue
      plane.physicsBody?.contactTestBitMask = CollisionCategory.bullets.rawValue


      plane.physicsBody?.applyForce(SCNVector3Make(0.0, 0.0, randSpeed), asImpulse: true)
      plane.runAction(planeAnimation)

      Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(addPlane), userInfo: nil, repeats: false)


      func getUserVector() -> (SCNVector3, SCNVector3) // (direction, position)
      if let frame = self.sceneView.session.currentFrame
      let mat = SCNMatrix4(frame.camera.transform) // 4x4 transform matrix describing camera in world space
      let dir = SCNVector3(-30 * mat.m31, -30 * mat.m32, -10 * mat.m33) // orientation of camera in world space
      let pos = SCNVector3(mat.m41, mat.m42, mat.m43) // location of camera in world space

      return (dir, pos)

      return (SCNVector3(0, 0, -1), SCNVector3(0, 0, -0.2))


      // MARK: - Scene Handling
      override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
      if gameHasStarted


      let bulletsNode = Bullet()

      let (direction, position) = self.getUserVector()
      bulletsNode.position = position // SceneKit/AR coordinates are in meters

      let bulletDirection = direction

      bulletsNode.physicsBody?.velocity = SCNVector3Make(0.0, 0.0, -5)
      bulletsNode.physicsBody?.applyForce(bulletDirection, asImpulse: true)
      sceneView.scene.rootNode.addChildNode(bulletsNode)


      guard let touch = touches.first else return
      let touchLocation = touch.location(in: view)

      guard let hitTestTouch = sceneView.hitTest(touchLocation, options: nil).first else return
      let touchedNode = hitTestTouch.node

      guard touchedNode.name == "plane" else return
      touchedNode.physicsBody?.isAffectedByGravity = true
      touchedNode.physicsBody?.applyTorque(SCNVector4Make(0.0, 0.3, 1.0, 1.0), asImpulse: true)
      score += 1

      let explosion = SCNParticleSystem(named: "Explosion.scnp", inDirectory: nil)!
      touchedNode.addParticleSystem(explosion)
      else
      guard foundSurface else return

      gameHasStarted = true
      visNode.removeFromParentNode()

      // Score Lbl
      scoreLbl = UILabel(frame: CGRect(x: 0.0, y: view.frame.height * 0.05, width: view.frame.width, height: view.frame.height * 0.1))
      scoreLbl.textColor = .yellow
      scoreLbl.font = UIFont(name: "Arial", size: view.frame.width * 0.1)
      scoreLbl.text = "0"
      scoreLbl.textAlignment = .center

      view.addSubview(scoreLbl)

      // Main Container
      mainContainer = sceneView.scene.rootNode.childNode(withName: "mainContainer", recursively: false)!
      mainContainer.isHidden = false
      mainContainer.position = gamePos

      // Lighting (Ambient)
      let ambientLight = SCNLight()
      ambientLight.type = .ambient
      ambientLight.color = UIColor.white
      ambientLight.intensity = 300.0

      let ambientLightNode = SCNNode()
      ambientLightNode.light = ambientLight
      ambientLightNode.position.y = 2.0

      mainContainer.addChildNode(ambientLightNode)

      // Lighting (Omnidirectional)
      let omniLight = SCNLight()
      omniLight.type = .omni
      omniLight.color = UIColor.white
      omniLight.intensity = 1000.0

      let omniLightNode = SCNNode()
      omniLightNode.light = omniLight
      omniLightNode.position.y = 3.0

      mainContainer.addChildNode(omniLightNode)

      addPlane()



      func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval)
      guard !gameHasStarted else return
      guard let hitTest = sceneView.hitTest(CGPoint(x: view.frame.midX, y: view.frame.midY), types: [.existingPlane, .featurePoint, .estimatedHorizontalPlane]).last else return

      let transform = SCNMatrix4(hitTest.worldTransform)
      gamePos = SCNVector3Make(transform.m41, transform.m42, transform.m43)

      if visNode == nil
      let visPlane = SCNPlane(width: 0.3, height: 0.3)
      visPlane.firstMaterial?.diffuse.contents = #imageLiteral(resourceName: "tracker")

      visNode = SCNNode(geometry: visPlane)
      visNode.eulerAngles.x = .pi * -0.5

      sceneView.scene.rootNode.addChildNode(visNode)


      visNode.position = gamePos
      foundSurface = true


      func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact)


      func removeNodeWithAnimation(_ node: SCNNode, explosion: Bool)

      // Play collision sound for all collisions (bullet-bullet, etc.)

      self.playSoundEffect(ofType: .collision)

      if explosion

      // Play explosion sound for bullet-ship collisions

      self.playSoundEffect(ofType: .explosion)

      let particleSystem = SCNParticleSystem(named: "Explosion", inDirectory: nil)
      let systemNode = SCNNode()
      systemNode.addParticleSystem(particleSystem!)
      // place explosion where node is
      systemNode.position = node.position
      sceneView.scene.rootNode.addChildNode(systemNode)


      // remove node
      node.removeFromParentNode()


      // MARK: - Sound Effects

      func playSoundEffect(ofType effect: SoundEffect)

      // Async to avoid substantial cost to graphics processing (may result in sound effect delay however)
      DispatchQueue.main.async
      do

      if let effectURL = Bundle.main.url(forResource: effect.rawValue, withExtension: "mp3")

      self.player = try AVAudioPlayer(contentsOf: effectURL)
      self.player.play()



      catch let error as NSError
      print(error.description)




      func configureSession()
      if ARWorldTrackingConfiguration.isSupported // checks if user's device supports the more precise ARWorldTrackingSessionConfiguration
      // equivalent to `if utsname().hasAtLeastA9()`
      // Create a session configuration
      let configuration = ARWorldTrackingConfiguration()
      configuration.planeDetection = ARWorldTrackingConfiguration.PlaneDetection.horizontal

      // Run the view's session
      sceneView.session.run(configuration)
      else
      // slightly less immersive AR experience due to lower end processor
      let configuration = AROrientationTrackingConfiguration()

      // Run the view's session
      sceneView.session.run(configuration)






      struct CollisionCategory: OptionSet
      let rawValue: Int

      static let bullets = CollisionCategory(rawValue: 1 << 0) // 00...01
      static let ship = CollisionCategory(rawValue: 1 << 1) // 00..10


      extension utsname
      func hasAtLeastA9() -> Bool // checks if device has at least A9 chip for configuration
      var systemInfo = self
      uname(&systemInfo)
      let str = withUnsafePointer(to: &systemInfo.machine.0) ptr in
      return String(cString: ptr)

      switch str
      case "iPhone8,1", "iPhone8,2", "iPhone8,4", "iPhone9,1", "iPhone9,2", "iPhone9,3", "iPhone9,4": // iphone with at least A9 processor
      return true
      case "iPad6,7", "iPad6,8", "iPad6,3", "iPad6,4", "iPad6,11", "iPad6,12": // ipad with at least A9 processor
      return true
      default:
      return false




      enum SoundEffect: String
      case explosion = "explosion"
      case collision = "collision"
      case torpedo = "torpedo"



      Bullet.swift



      import UIKit
      import SceneKit

      // Spheres that are shot at the "ships"
      class Bullet: SCNNode
      override init ()
      super.init()
      let sphere = SCNSphere(radius: 0.025)
      self.geometry = sphere
      let shape = SCNPhysicsShape(geometry: sphere, options: nil)
      self.physicsBody = SCNPhysicsBody(type: .dynamic, shape: shape)
      self.physicsBody?.isAffectedByGravity = false
      // see http://texnotes.me/post/5/ for details on collisions and bit masks
      self.physicsBody?.categoryBitMask = CollisionCategory.bullets.rawValue
      self.physicsBody?.contactTestBitMask = CollisionCategory.ship.rawValue

      // add texture
      let material = SCNMaterial()
      material.diffuse.contents = UIImage(named: "bullet_texture")
      self.geometry?.materials = [material]


      required init?(coder aDecoder: NSCoder)
      fatalError("init(coder:) has not been implemented")











      share|improve this question














      I'm trying to make a collision effect when my jet is hit by a bullet or touched by the player directly. The animation and the touch explosion works.



      But when the bullet hits the jet planes it's not exploding.



      Note: Already tried adding
      sceneView.scene.physicsWorld.contactDelegate = self in viewDidLoad()



      //
      // ViewController.swift
      //

      import UIKit
      import SceneKit
      import ARKit

      class ViewController: UIViewController, ARSCNViewDelegate, SCNPhysicsContactDelegate
      // MARK: - Variables
      @IBOutlet var sceneView: ARSCNView!
      var visNode: SCNNode!
      var mainContainer: SCNNode!
      var gameHasStarted = false
      var foundSurface = false
      var gamePos = SCNVector3Make(0.0, 0.0, 0.0)
      var scoreLbl: UILabel!


      var player: AVAudioPlayer!


      var score = 0
      didSet
      scoreLbl.text = "(score)"



      // MARK: - View Controller Handling
      override func viewDidLoad()
      super.viewDidLoad()

      // Scene
      sceneView.delegate = self
      sceneView.showsStatistics = true

      let scene = SCNScene(named: "art.scnassets/scene.scn")!
      sceneView.scene = scene

      sceneView.scene.physicsWorld.contactDelegate = self


      override func viewWillAppear(_ animated: Bool)
      super.viewWillAppear(animated)

      //let configuration = ARWorldTrackingConfiguration()
      //sceneView.session.run(configuration)


      self.configureSession()


      override func viewWillDisappear(_ animated: Bool)
      super.viewWillDisappear(animated)

      sceneView.session.pause()


      // MARK: - Custom functions
      func randomPos() -> SCNVector3
      let randX = (Float(arc4random_uniform(200)) / 100.0) - 1.0
      let randY = (Float(arc4random_uniform(100)) / 100.0) + 1.5

      return SCNVector3Make(randX, randY, -5.0)


      @objc func addPlane()
      let plane = sceneView.scene.rootNode.childNode(withName: "plane", recursively: false)?.copy() as! SCNNode
      plane.position = randomPos()
      plane.isHidden = false

      mainContainer.addChildNode(plane)

      let randSpeed = Float(arc4random_uniform(3) + 1)
      //original - let randSpeed = Float(arc4random_uniform(3) + 3)
      let planeAnimation = SCNAction.sequence([SCNAction.wait(duration: 10.0), SCNAction.fadeOut(duration: 1.0), SCNAction.removeFromParentNode()])
      plane.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
      plane.physicsBody?.isAffectedByGravity = false

      plane.physicsBody?.categoryBitMask = CollisionCategory.ship.rawValue
      plane.physicsBody?.contactTestBitMask = CollisionCategory.bullets.rawValue


      plane.physicsBody?.applyForce(SCNVector3Make(0.0, 0.0, randSpeed), asImpulse: true)
      plane.runAction(planeAnimation)

      Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(addPlane), userInfo: nil, repeats: false)


      func getUserVector() -> (SCNVector3, SCNVector3) // (direction, position)
      if let frame = self.sceneView.session.currentFrame
      let mat = SCNMatrix4(frame.camera.transform) // 4x4 transform matrix describing camera in world space
      let dir = SCNVector3(-30 * mat.m31, -30 * mat.m32, -10 * mat.m33) // orientation of camera in world space
      let pos = SCNVector3(mat.m41, mat.m42, mat.m43) // location of camera in world space

      return (dir, pos)

      return (SCNVector3(0, 0, -1), SCNVector3(0, 0, -0.2))


      // MARK: - Scene Handling
      override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
      if gameHasStarted


      let bulletsNode = Bullet()

      let (direction, position) = self.getUserVector()
      bulletsNode.position = position // SceneKit/AR coordinates are in meters

      let bulletDirection = direction

      bulletsNode.physicsBody?.velocity = SCNVector3Make(0.0, 0.0, -5)
      bulletsNode.physicsBody?.applyForce(bulletDirection, asImpulse: true)
      sceneView.scene.rootNode.addChildNode(bulletsNode)


      guard let touch = touches.first else return
      let touchLocation = touch.location(in: view)

      guard let hitTestTouch = sceneView.hitTest(touchLocation, options: nil).first else return
      let touchedNode = hitTestTouch.node

      guard touchedNode.name == "plane" else return
      touchedNode.physicsBody?.isAffectedByGravity = true
      touchedNode.physicsBody?.applyTorque(SCNVector4Make(0.0, 0.3, 1.0, 1.0), asImpulse: true)
      score += 1

      let explosion = SCNParticleSystem(named: "Explosion.scnp", inDirectory: nil)!
      touchedNode.addParticleSystem(explosion)
      else
      guard foundSurface else return

      gameHasStarted = true
      visNode.removeFromParentNode()

      // Score Lbl
      scoreLbl = UILabel(frame: CGRect(x: 0.0, y: view.frame.height * 0.05, width: view.frame.width, height: view.frame.height * 0.1))
      scoreLbl.textColor = .yellow
      scoreLbl.font = UIFont(name: "Arial", size: view.frame.width * 0.1)
      scoreLbl.text = "0"
      scoreLbl.textAlignment = .center

      view.addSubview(scoreLbl)

      // Main Container
      mainContainer = sceneView.scene.rootNode.childNode(withName: "mainContainer", recursively: false)!
      mainContainer.isHidden = false
      mainContainer.position = gamePos

      // Lighting (Ambient)
      let ambientLight = SCNLight()
      ambientLight.type = .ambient
      ambientLight.color = UIColor.white
      ambientLight.intensity = 300.0

      let ambientLightNode = SCNNode()
      ambientLightNode.light = ambientLight
      ambientLightNode.position.y = 2.0

      mainContainer.addChildNode(ambientLightNode)

      // Lighting (Omnidirectional)
      let omniLight = SCNLight()
      omniLight.type = .omni
      omniLight.color = UIColor.white
      omniLight.intensity = 1000.0

      let omniLightNode = SCNNode()
      omniLightNode.light = omniLight
      omniLightNode.position.y = 3.0

      mainContainer.addChildNode(omniLightNode)

      addPlane()



      func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval)
      guard !gameHasStarted else return
      guard let hitTest = sceneView.hitTest(CGPoint(x: view.frame.midX, y: view.frame.midY), types: [.existingPlane, .featurePoint, .estimatedHorizontalPlane]).last else return

      let transform = SCNMatrix4(hitTest.worldTransform)
      gamePos = SCNVector3Make(transform.m41, transform.m42, transform.m43)

      if visNode == nil
      let visPlane = SCNPlane(width: 0.3, height: 0.3)
      visPlane.firstMaterial?.diffuse.contents = #imageLiteral(resourceName: "tracker")

      visNode = SCNNode(geometry: visPlane)
      visNode.eulerAngles.x = .pi * -0.5

      sceneView.scene.rootNode.addChildNode(visNode)


      visNode.position = gamePos
      foundSurface = true


      func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact)


      func removeNodeWithAnimation(_ node: SCNNode, explosion: Bool)

      // Play collision sound for all collisions (bullet-bullet, etc.)

      self.playSoundEffect(ofType: .collision)

      if explosion

      // Play explosion sound for bullet-ship collisions

      self.playSoundEffect(ofType: .explosion)

      let particleSystem = SCNParticleSystem(named: "Explosion", inDirectory: nil)
      let systemNode = SCNNode()
      systemNode.addParticleSystem(particleSystem!)
      // place explosion where node is
      systemNode.position = node.position
      sceneView.scene.rootNode.addChildNode(systemNode)


      // remove node
      node.removeFromParentNode()


      // MARK: - Sound Effects

      func playSoundEffect(ofType effect: SoundEffect)

      // Async to avoid substantial cost to graphics processing (may result in sound effect delay however)
      DispatchQueue.main.async
      do

      if let effectURL = Bundle.main.url(forResource: effect.rawValue, withExtension: "mp3")

      self.player = try AVAudioPlayer(contentsOf: effectURL)
      self.player.play()



      catch let error as NSError
      print(error.description)




      func configureSession()
      if ARWorldTrackingConfiguration.isSupported // checks if user's device supports the more precise ARWorldTrackingSessionConfiguration
      // equivalent to `if utsname().hasAtLeastA9()`
      // Create a session configuration
      let configuration = ARWorldTrackingConfiguration()
      configuration.planeDetection = ARWorldTrackingConfiguration.PlaneDetection.horizontal

      // Run the view's session
      sceneView.session.run(configuration)
      else
      // slightly less immersive AR experience due to lower end processor
      let configuration = AROrientationTrackingConfiguration()

      // Run the view's session
      sceneView.session.run(configuration)






      struct CollisionCategory: OptionSet
      let rawValue: Int

      static let bullets = CollisionCategory(rawValue: 1 << 0) // 00...01
      static let ship = CollisionCategory(rawValue: 1 << 1) // 00..10


      extension utsname
      func hasAtLeastA9() -> Bool // checks if device has at least A9 chip for configuration
      var systemInfo = self
      uname(&systemInfo)
      let str = withUnsafePointer(to: &systemInfo.machine.0) ptr in
      return String(cString: ptr)

      switch str
      case "iPhone8,1", "iPhone8,2", "iPhone8,4", "iPhone9,1", "iPhone9,2", "iPhone9,3", "iPhone9,4": // iphone with at least A9 processor
      return true
      case "iPad6,7", "iPad6,8", "iPad6,3", "iPad6,4", "iPad6,11", "iPad6,12": // ipad with at least A9 processor
      return true
      default:
      return false




      enum SoundEffect: String
      case explosion = "explosion"
      case collision = "collision"
      case torpedo = "torpedo"



      Bullet.swift



      import UIKit
      import SceneKit

      // Spheres that are shot at the "ships"
      class Bullet: SCNNode
      override init ()
      super.init()
      let sphere = SCNSphere(radius: 0.025)
      self.geometry = sphere
      let shape = SCNPhysicsShape(geometry: sphere, options: nil)
      self.physicsBody = SCNPhysicsBody(type: .dynamic, shape: shape)
      self.physicsBody?.isAffectedByGravity = false
      // see http://texnotes.me/post/5/ for details on collisions and bit masks
      self.physicsBody?.categoryBitMask = CollisionCategory.bullets.rawValue
      self.physicsBody?.contactTestBitMask = CollisionCategory.ship.rawValue

      // add texture
      let material = SCNMaterial()
      material.diffuse.contents = UIImage(named: "bullet_texture")
      self.geometry?.materials = [material]


      required init?(coder aDecoder: NSCoder)
      fatalError("init(coder:) has not been implemented")








      ios swift xcode swift4






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Mar 21 at 19:07









      nanospecknanospeck

      1,78422332




      1,78422332






















          0






          active

          oldest

          votes












          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55287637%2fswift-4-func-physicsworld-not-invoked-on-collision%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55287637%2fswift-4-func-physicsworld-not-invoked-on-collision%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

          Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript