iosswiftscenekitsceneview

Adding physicsBody makes the ar object disappear


I am trying to add simple 3D objects to sceneView. Adding object to the view is rather straightforward and went smoothly. However when I tried to add body for collision purposes (boxNode.physicsBody = boxBody), the cube completely disappeared and I cannot find the cube anymore.

Did I miss something? I have attached my code below. Rest of the project is generated by the project setting selecting "AR app"

import UIKit
import SceneKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate, ARCoachingOverlayViewDelegate {

    @IBOutlet var sceneView: ARSCNView!
    
    let coachingOverlay = ARCoachingOverlayView()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set the view's delegate
        sceneView.delegate = self
        
        // Show statistics such as fps and timing information
        sceneView.showsStatistics = true
        
        
        let box = SCNBox(width: 0.05, height: 0.05, length: 0.05, chamferRadius: 0)
        let boxNode = SCNNode(geometry: box)
        let boxBody = SCNPhysicsBody(type: .dynamic, shape: nil)

        box.firstMaterial?.diffuse.contents = UIColor.red
        boxNode.position = SCNVector3(0.1,0,0)
//        boxBody.mass = 1
////        boxBody.categoryBitMask = CollisionBitmask.box.rawValue
        boxNode.physicsBody = boxBody
//        boxNode.rotation = SCNVector4Make(1, 1, 1, 1)
//        boxNode.name = "box"
        sceneView.scene.rootNode.addChildNode(boxNode)
        let scene = SCNScene()
        sceneView.scene = scene
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // Create a session configuration
        let configuration = ARWorldTrackingConfiguration()

        // Run the view's session
        sceneView.session.run(configuration)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        // Pause the view's session
        sceneView.session.pause()
    }

    // MARK: - ARSCNViewDelegate
    
/*
    // Override to create and configure nodes for anchors added to the view's session.
    func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
        let node = SCNNode()
     
        return node
    }
*/
    
    func session(_ session: ARSession, didFailWithError error: Error) {
        // Present an error message to the user
        
    }
    
    func sessionWasInterrupted(_ session: ARSession) {
        // Inform the user that the session has been interrupted, for example, by presenting an overlay
        
    }
    
    func sessionInterruptionEnded(_ session: ARSession) {
        // Reset tracking and/or remove existing anchors if consistent tracking is required
        
    }
    
}

Solution

  • Use isAffectedByGravity instance property to get rid of object's gravity:

    var isAffectedByGravity: Bool { get set }
    

    You need false value (by default it's true):

    let sphere = SCNSphere(radius: 1)
    let node = SCNNode(geometry: sphere)
    let physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
    
    node.physicsBody = physicsBody
    physicsBody.isAffectedByGravity = false
    sceneView.scene.rootNode.addChildNode(node)